diff --git a/dapr/clients/http/dapr_invocation_http_client.py b/dapr/clients/http/dapr_invocation_http_client.py index 604c483c0..be572cccb 100644 --- a/dapr/clients/http/dapr_invocation_http_client.py +++ b/dapr/clients/http/dapr_invocation_http_client.py @@ -157,11 +157,17 @@ def invoke_method( try: loop = asyncio.get_running_loop() + owns_loop = False except RuntimeError: loop = asyncio.new_event_loop() + owns_loop = True asyncio.set_event_loop(loop) awaitable = self.invoke_method_async( app_id, method_name, data, content_type, metadata, http_verb, http_querystring, timeout ) - return loop.run_until_complete(awaitable) + try: + return loop.run_until_complete(awaitable) + finally: + if owns_loop: + loop.close() diff --git a/tests/clients/test_http_service_invocation_client.py b/tests/clients/test_http_service_invocation_client.py index a0a7aadd6..76a209bcc 100644 --- a/tests/clients/test_http_service_invocation_client.py +++ b/tests/clients/test_http_service_invocation_client.py @@ -65,6 +65,21 @@ def test_basic_invoke(self): self.assertEqual(b'STRING_BODY', response.data) self.assertEqual(self.invoke_url, self.server.request_path()) + def test_invoke_closes_the_event_loop_it_creates(self): + self.server.set_response(b'STRING_BODY') + + import asyncio + import warnings + + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter('always') + self.client.invoke_method(self.app_id, self.method_name, '') + self.client.invoke_method(self.app_id, self.method_name, '') + + unclosed_loop_warnings = [w for w in caught if 'unclosed event loop' in str(w.message)] + self.assertEqual([], unclosed_loop_warnings) + self.assertTrue(asyncio.get_event_loop_policy().get_event_loop().is_closed()) + def test_coroutine_basic_invoke(self): self.server.set_response(b'STRING_BODY')