Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add an outbound health check #641

Closed

Conversation

mukundansundar
Copy link
Contributor

Description

closes #611

Issue reference

We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.

Please reference the issue this PR will close: #611

Checklist

Please make sure you've completed the relevant tasks for this PR, out of the following list:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

Signed-off-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com>
Copy link
Contributor Author

@mukundansundar mukundansundar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to split out health check apis from the service invocation api, so that even when service invocation protocol is chosen as grpc, http is still used as the health check protocol.

@@ -173,3 +175,27 @@ async def invoke_method_async(
else:
raise NotImplementedError(
'Please use `dapr.aio.clients.DaprClient` for async invocation')

def wait(self, timeout_s: float):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is float because DaprGrpcClient already has a method wait as float, I can remove that method if that would be better....

"""
self.helath_client.wait(int(timeout_s))

async def wait_async(self, timeout_s: float):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is float because DaprGrpcClient already has a method wait as float, I can remove that method if that would be better....

"""Dapr Health Client"""

def __init__(self, timeout: Optional[int] = 60):
self._client = DaprHttpClient(DefaultJSONSerializer(), timeout, None, None)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a need to pass in address from DaprClient initialization?
Both http and grpc might not have the same endpoint address.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's unrelated to this PR IMO. We can open an issue for discussion in the future. I don't think we need to tackle that until someone has a concrete need for it. The HTTP Client is only used by Actors and by Service Invocation (and now the health client), though using the SDK for service invocation is no longer the recommended way. Perhaps you can take a look how the DotNet SDK handles this and compare.

Copy link

codecov bot commented Nov 23, 2023

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (6ee22eb) 86.16% compared to head (2bdcb3d) 86.23%.

Files Patch % Lines
dapr/clients/__init__.py 66.66% 2 Missing ⚠️
dapr/aio/clients/__init__.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #641      +/-   ##
==========================================
+ Coverage   86.16%   86.23%   +0.07%     
==========================================
  Files          75       76       +1     
  Lines        3737     3779      +42     
==========================================
+ Hits         3220     3259      +39     
- Misses        517      520       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@berndverst berndverst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating another instance of DaprHTTPClient and also the Serializer - why not a simple static utility method that uses urllib ? I would much prefer that.

That method could then be imported within the wait methods and used there.

Allocating an entire Dapr HTTP Client with Serializer just feels inefficient from a memory perspective.

@berndverst
Copy link
Member

Your change broke the configuration API example by the way

		== APP == Traceback (most recent call last):
		== APP ==   File "configuration.py", line 47, in <module>
		== APP ==     asyncio.run(executeConfiguration())
		== APP ==   File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/asyncio/runners.py", line 44, in run
		== APP ==     return loop.run_until_complete(main)
		== APP ==   File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
		== APP ==     return future.result()
		== APP ==   File "configuration.py", line 25, in executeConfiguration
		== APP ==     d.wait(20)
		== APP ==   File "/home/runner/work/python-sdk/python-sdk/dapr/clients/__init__.py", line 189, in wait
		== APP ==     self.helath_client.wait(int(timeout_s))
		== APP ==   File "/home/runner/work/python-sdk/python-sdk/dapr/clients/http/helpers.py", line 81, in wait
		== APP ==     loop.run_until_complete(awaitable)
		== APP ==   File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/asyncio/base_events.py", line 592, in run_until_complete
		== APP ==     self._check_running()
		== APP ==   File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/asyncio/base_events.py", line 552, in _check_running
		== APP ==     raise RuntimeError('This event loop is already running')
		== APP == RuntimeError: This event loop is already running
		== APP == sys:1: RuntimeWarning: coroutine 'DaprHealthClient.wait_async' was never awaited

@@ -72,6 +73,7 @@ def __init__(
"""
super().__init__(address, interceptors, max_grpc_message_length)
self.invocation_client = None
self.helath_client = DaprHealthClient(timeout=http_timeout_seconds)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.helath_client = DaprHealthClient(timeout=http_timeout_seconds)
self.health_client = DaprHealthClient(timeout=http_timeout_seconds)

@mukundansundar
Copy link
Contributor Author

Instead of creating another instance of DaprHTTPClient and also the Serializer - why not a simple static utility method that uses urllib ? I would much prefer that.

That method could then be imported within the wait methods and used there.

Allocating an entire Dapr HTTP Client with Serializer just feels inefficient from a memory perspective.

will change the PR to use urllib instead.

@berndverst
Copy link
Member

Update on this?

@berndverst berndverst closed this Feb 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Check outbound healthz endpoint on sidecar wait
2 participants