From 6a73f6f50cfe8ecaf3a3e90ec2e91f1757ea842c Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:50:56 -0400 Subject: [PATCH 1/6] Clean up AsyncIO Loop Usage Where Possible to Patch Exception --- .../clients/dispatcher/action_listener.py | 14 ++--- hatchet_sdk/clients/event_ts.py | 4 +- hatchet_sdk/clients/rest_client.py | 3 +- hatchet_sdk/utils/aio_utils.py | 51 +++++++++++++++++-- hatchet_sdk/worker/action_listener_process.py | 6 ++- hatchet_sdk/worker/runner/run_loop_manager.py | 3 +- hatchet_sdk/worker/runner/runner.py | 34 ++++++++----- hatchet_sdk/worker/worker.py | 13 ++--- hatchet_sdk/workflow_run.py | 2 +- 9 files changed, 90 insertions(+), 40 deletions(-) diff --git a/hatchet_sdk/clients/dispatcher/action_listener.py b/hatchet_sdk/clients/dispatcher/action_listener.py index ebcf9a16..11653778 100644 --- a/hatchet_sdk/clients/dispatcher/action_listener.py +++ b/hatchet_sdk/clients/dispatcher/action_listener.py @@ -22,6 +22,7 @@ ) from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub from hatchet_sdk.logger import logger +from hatchet_sdk.utils.aio_utils import create_new_event_loop, get_active_event_loop from hatchet_sdk.utils.backoff import exp_backoff_sleep from ...loader import ClientConfig @@ -184,15 +185,10 @@ async def heartbeat(self): async def start_heartbeater(self): if self.heartbeat_task is not None: return - - try: - loop = asyncio.get_event_loop() - except RuntimeError as e: - if str(e).startswith("There is no current event loop in thread"): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - else: - raise e + loop = get_active_event_loop(should_raise=False) + if not loop: + loop = create_new_event_loop() + asyncio.set_event_loop(loop) self.heartbeat_task = loop.create_task(self.heartbeat()) def __aiter__(self): diff --git a/hatchet_sdk/clients/event_ts.py b/hatchet_sdk/clients/event_ts.py index 1d3c3978..6be66697 100644 --- a/hatchet_sdk/clients/event_ts.py +++ b/hatchet_sdk/clients/event_ts.py @@ -1,6 +1,8 @@ import asyncio from typing import Any +from hatchet_sdk.utils.aio_utils import get_active_event_loop + class Event_ts(asyncio.Event): """ @@ -10,7 +12,7 @@ class Event_ts(asyncio.Event): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self._loop is None: - self._loop = asyncio.get_event_loop() + self._loop = get_active_event_loop() def set(self): if not self._loop.is_closed(): diff --git a/hatchet_sdk/clients/rest_client.py b/hatchet_sdk/clients/rest_client.py index 80659d43..12c7e10f 100644 --- a/hatchet_sdk/clients/rest_client.py +++ b/hatchet_sdk/clients/rest_client.py @@ -42,6 +42,7 @@ WorkflowRunsCancelRequest, ) from hatchet_sdk.clients.rest.models.workflow_version import WorkflowVersion +from hatchet_sdk.utils.aio_utils import create_new_event_loop class AsyncRestApi: @@ -246,7 +247,7 @@ async def events_replay(self, event_ids: list[str] | EventList) -> EventList: class RestApi: def __init__(self, host: str, api_key: str, tenant_id: str): - self._loop = asyncio.new_event_loop() + self._loop = create_new_event_loop() self._thread = threading.Thread(target=self._run_event_loop, daemon=True) self._thread.start() diff --git a/hatchet_sdk/utils/aio_utils.py b/hatchet_sdk/utils/aio_utils.py index bd897cf7..80806951 100644 --- a/hatchet_sdk/utils/aio_utils.py +++ b/hatchet_sdk/utils/aio_utils.py @@ -55,7 +55,7 @@ async def run(*args, loop=None, executor=None, **kwargs): The result of the function call. """ if loop is None: - loop = asyncio.get_running_loop() + loop = get_active_event_loop() if inspect.iscoroutinefunction(func): # Wrap the coroutine to run it in an executor @@ -80,7 +80,7 @@ def __init__(self): Initializes the EventLoopThread by creating an event loop and setting up a thread to run the loop. """ - self.loop = asyncio.new_event_loop() + self.loop = create_new_event_loop() self.thread = Thread(target=self.run_loop_in_thread, args=(self.loop,)) def __enter__(self) -> asyncio.AbstractEventLoop: @@ -111,7 +111,7 @@ def run_loop_in_thread(self, loop: asyncio.AbstractEventLoop) -> None: loop.run_forever() -def get_active_event_loop() -> asyncio.AbstractEventLoop | None: +def get_active_event_loop(should_raise=True) -> asyncio.AbstractEventLoop | None: """ Get the active event loop. @@ -120,9 +120,50 @@ def get_active_event_loop() -> asyncio.AbstractEventLoop | None: event loop in the current thread. """ try: - return asyncio.get_event_loop() + loop = asyncio.get_event_loop() + patch_exception_handler(loop) + return loop except RuntimeError as e: - if str(e).startswith("There is no current event loop in thread"): + if ( + str(e).startswith("There is no current event loop in thread") + and not should_raise + ): return None else: raise e + + +def create_new_event_loop() -> asyncio.AbstractEventLoop | None: + """ + Create a new event loop. + + Returns: + asyncio.AbstractEventLoop: The new event loop. + """ + loop = asyncio.new_event_loop() + patch_exception_handler(loop) + return loop + + +def patch_exception_handler(loop: asyncio.AbstractEventLoop) -> None: + """ + Patch the asyncio exception handler to ignore `BlockingIOError: [Errno 35] Resource temporarily unavailable` + errors caused by `aio.grpc` when using multiple event loops in separate threads. + + This error arises from a Cython implementation detail in `aio.Channel.__init__`, where a `socket.recv(1)` call + succeeds only on the first invocation. Subsequent calls result in the mentioned error, but this does not + impact the functionality of the library and can be safely ignored. + + References: + - https://github.com/grpc/grpc/issues/25364 + - https://github.com/grpc/grpc/pull/36096 + """ + + def exception_handler(loop: asyncio.AbstractEventLoop, context: dict) -> None: + if "exception" in context: + err = f"{type(context['exception']).__name__}: {context['exception']}" + if err == "BlockingIOError: [Errno 35] Resource temporarily unavailable": + return + loop.default_exception_handler(context) + + loop.set_exception_handler(exception_handler) diff --git a/hatchet_sdk/worker/action_listener_process.py b/hatchet_sdk/worker/action_listener_process.py index 33463f04..0135aa69 100644 --- a/hatchet_sdk/worker/action_listener_process.py +++ b/hatchet_sdk/worker/action_listener_process.py @@ -21,6 +21,7 @@ ) from hatchet_sdk.loader import ClientConfig from hatchet_sdk.logger import logger +from hatchet_sdk.utils.aio_utils import get_active_event_loop, patch_exception_handler from hatchet_sdk.utils.backoff import exp_backoff_sleep ACTION_EVENT_RETRY_COUNT = 5 @@ -70,7 +71,8 @@ def __post_init__(self): if self.debug: logger.setLevel(logging.DEBUG) - loop = asyncio.get_event_loop() + loop = get_active_event_loop() + patch_exception_handler(loop) loop.add_signal_handler(signal.SIGINT, noop_handler) loop.add_signal_handler(signal.SIGTERM, noop_handler) loop.add_signal_handler( @@ -111,7 +113,7 @@ async def start(self, retry_attempt=0): # TODO move event methods to separate class async def _get_event(self): - loop = asyncio.get_running_loop() + loop = get_active_event_loop() return await loop.run_in_executor(None, self.event_queue.get) async def start_event_send_loop(self): diff --git a/hatchet_sdk/worker/runner/run_loop_manager.py b/hatchet_sdk/worker/runner/run_loop_manager.py index c6f38dae..39ea69e5 100644 --- a/hatchet_sdk/worker/runner/run_loop_manager.py +++ b/hatchet_sdk/worker/runner/run_loop_manager.py @@ -8,6 +8,7 @@ from hatchet_sdk.clients.dispatcher.action_listener import Action from hatchet_sdk.loader import ClientConfig from hatchet_sdk.logger import logger +from hatchet_sdk.utils.aio_utils import get_active_event_loop from hatchet_sdk.worker.runner.runner import Runner from hatchet_sdk.worker.runner.utils.capture_logs import capture_logs @@ -50,7 +51,7 @@ async def async_start(self, retry_count=1): async def _async_start(self, retry_count=1): logger.info("starting runner...") - self.loop = asyncio.get_running_loop() + self.loop = get_active_event_loop() k = self.loop.create_task(self._start_action_loop()) def cleanup(self): diff --git a/hatchet_sdk/worker/runner/runner.py b/hatchet_sdk/worker/runner/runner.py index d37da955..005e4384 100644 --- a/hatchet_sdk/worker/runner/runner.py +++ b/hatchet_sdk/worker/runner/runner.py @@ -33,6 +33,7 @@ ) from hatchet_sdk.loader import ClientConfig from hatchet_sdk.logger import logger +from hatchet_sdk.utils.aio_utils import create_new_event_loop, get_active_event_loop from hatchet_sdk.v2.callable import DurableContext from hatchet_sdk.worker.action_listener_process import ActionEvent @@ -284,19 +285,24 @@ async def async_wrapped_action_func( ) or asyncio.iscoroutinefunction(action_func): return await action_func(context) else: - pfunc = functools.partial( - # we must copy the context vars to the new thread, as only asyncio natively supports - # contextvars - copy_context_vars, - contextvars.copy_context().items(), - self.thread_action_func, - context, - action_func, - action, - ) - loop = asyncio.get_event_loop() - res = await loop.run_in_executor(self.thread_pool, pfunc) + def thread_action_wrapper(): + loop = create_new_event_loop() + asyncio.set_event_loop(loop) + + wr.set(context.workflow_run_id()) + sr.set(context.step_run_id) + + try: + result = action_func(context) + return result + finally: + loop.close() + + loop = get_active_event_loop() + res = await loop.run_in_executor( + self.thread_pool, thread_action_wrapper + ) return res except Exception as e: @@ -363,7 +369,7 @@ async def handle_start_step_run(self, action: Action): ) ) - loop = asyncio.get_event_loop() + loop = get_active_event_loop() task = loop.create_task( self.async_wrapped_action_func( context, action_func, action, action.step_run_id @@ -406,7 +412,7 @@ async def handle_start_group_key_run(self, action: Action): ) ) - loop = asyncio.get_event_loop() + loop = get_active_event_loop() task = loop.create_task( self.async_wrapped_action_func( context, action_func, action, action.get_group_key_run_id diff --git a/hatchet_sdk/worker/worker.py b/hatchet_sdk/worker/worker.py index 315f2f4a..c0e962c7 100644 --- a/hatchet_sdk/worker/worker.py +++ b/hatchet_sdk/worker/worker.py @@ -13,6 +13,7 @@ from hatchet_sdk.contracts.workflows_pb2 import CreateWorkflowVersionOpts from hatchet_sdk.loader import ClientConfig from hatchet_sdk.logger import logger +from hatchet_sdk.utils.aio_utils import create_new_event_loop, get_active_event_loop from hatchet_sdk.v2.callable import HatchetCallable from hatchet_sdk.worker.action_listener_process import worker_action_listener_process from hatchet_sdk.worker.runner.run_loop_manager import WorkerActionRunLoopManager @@ -102,15 +103,15 @@ def action_function(context): def status(self) -> WorkerStatus: return self._status - def setup_loop(self, loop: asyncio.AbstractEventLoop = None): - try: - loop = loop or asyncio.get_running_loop() - self.loop = loop + def setup_loop(self, loop: asyncio.AbstractEventLoop | None = None): + loop = loop or get_active_event_loop(should_raise=False) + if loop: created_loop = False logger.debug("using existing event loop") + self.loop = loop return created_loop - except RuntimeError: - self.loop = asyncio.new_event_loop() + else: + self.loop = create_new_event_loop() logger.debug("creating new event loop") asyncio.set_event_loop(self.loop) created_loop = True diff --git a/hatchet_sdk/workflow_run.py b/hatchet_sdk/workflow_run.py index 43452b7e..90bb602f 100644 --- a/hatchet_sdk/workflow_run.py +++ b/hatchet_sdk/workflow_run.py @@ -32,7 +32,7 @@ def result(self) -> Coroutine: return self.workflow_listener.result(self.workflow_run_id) def sync_result(self) -> dict: - loop = get_active_event_loop() + loop = get_active_event_loop(should_raise=False) if loop is None: with EventLoopThread() as loop: coro = self.workflow_listener.result(self.workflow_run_id) From 662c479e791be24de2d1d8d692a0fada4b2d7335 Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:51:17 -0400 Subject: [PATCH 2/6] Dep Clean Up --- poetry.lock | 337 +++++++++++++++++++++++++------------------------ pyproject.toml | 30 ++--- 2 files changed, 184 insertions(+), 183 deletions(-) diff --git a/poetry.lock b/poetry.lock index a68f1df1..7d5e1a35 100644 --- a/poetry.lock +++ b/poetry.lock @@ -153,18 +153,21 @@ frozenlist = ">=1.1.0" [[package]] name = "aiostream" -version = "0.5.2" +version = "0.6.2" description = "Generator-based operators for asynchronous iteration" optional = false python-versions = ">=3.8" files = [ - {file = "aiostream-0.5.2-py3-none-any.whl", hash = "sha256:054660370be9d37f6fe3ece3851009240416bd082e469fd90cc8673d3818cf71"}, - {file = "aiostream-0.5.2.tar.gz", hash = "sha256:b71b519a2d66c38f0872403ab86417955b77352f08d9ad02ad46fc3926b389f4"}, + {file = "aiostream-0.6.2-py3-none-any.whl", hash = "sha256:e771bfb0a8d6f5e04359992025315fa4cc3b908ddb02822f73bb57d6ed7e9125"}, + {file = "aiostream-0.6.2.tar.gz", hash = "sha256:481e58c7f94b98f37a81384411ee39336dffb933784753b1cfa0a26f3681cc2c"}, ] [package.dependencies] typing-extensions = "*" +[package.extras] +dev = ["pytest", "pytest-asyncio", "pytest-cov"] + [[package]] name = "annotated-types" version = "0.7.0" @@ -377,64 +380,62 @@ protobuf = ["grpcio-tools (>=1.66.1)"] [[package]] name = "grpcio-tools" -version = "1.62.3" +version = "1.66.1" description = "Protobuf code generator for gRPC" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "grpcio-tools-1.62.3.tar.gz", hash = "sha256:7c7136015c3d62c3eef493efabaf9e3380e3e66d24ee8e94c01cb71377f57833"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2f968b049c2849540751ec2100ab05e8086c24bead769ca734fdab58698408c1"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0a8c0c4724ae9c2181b7dbc9b186df46e4f62cb18dc184e46d06c0ebeccf569e"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5782883a27d3fae8c425b29a9d3dcf5f47d992848a1b76970da3b5a28d424b26"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d812daffd0c2d2794756bd45a353f89e55dc8f91eb2fc840c51b9f6be62667"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b47d0dda1bdb0a0ba7a9a6de88e5a1ed61f07fad613964879954961e36d49193"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ca246dffeca0498be9b4e1ee169b62e64694b0f92e6d0be2573e65522f39eea9"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-win32.whl", hash = "sha256:6a56d344b0bab30bf342a67e33d386b0b3c4e65868ffe93c341c51e1a8853ca5"}, - {file = "grpcio_tools-1.62.3-cp310-cp310-win_amd64.whl", hash = "sha256:710fecf6a171dcbfa263a0a3e7070e0df65ba73158d4c539cec50978f11dad5d"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:703f46e0012af83a36082b5f30341113474ed0d91e36640da713355cd0ea5d23"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7cc83023acd8bc72cf74c2edbe85b52098501d5b74d8377bfa06f3e929803492"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ff7d58a45b75df67d25f8f144936a3e44aabd91afec833ee06826bd02b7fbe7"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f2483ea232bd72d98a6dc6d7aefd97e5bc80b15cd909b9e356d6f3e326b6e43"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:962c84b4da0f3b14b3cdb10bc3837ebc5f136b67d919aea8d7bb3fd3df39528a"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8ad0473af5544f89fc5a1ece8676dd03bdf160fb3230f967e05d0f4bf89620e3"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-win32.whl", hash = "sha256:db3bc9fa39afc5e4e2767da4459df82b095ef0cab2f257707be06c44a1c2c3e5"}, - {file = "grpcio_tools-1.62.3-cp311-cp311-win_amd64.whl", hash = "sha256:e0898d412a434e768a0c7e365acabe13ff1558b767e400936e26b5b6ed1ee51f"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:d102b9b21c4e1e40af9a2ab3c6d41afba6bd29c0aa50ca013bf85c99cdc44ac5"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0a52cc9444df978438b8d2332c0ca99000521895229934a59f94f37ed896b133"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141d028bf5762d4a97f981c501da873589df3f7e02f4c1260e1921e565b376fa"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a5c093ab256dec5714a7a345f8cc89315cb57c298b276fa244f37a0ba507f0"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e02d7c1a02e3814c94ba0cfe43d93e872c758bd8fd5c2797f894d0c49b4a1dfc"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-win32.whl", hash = "sha256:b881fd9505a84457e9f7e99362eeedd86497b659030cf57c6f0070df6d9c2b9b"}, - {file = "grpcio_tools-1.62.3-cp312-cp312-win_amd64.whl", hash = "sha256:11c625eebefd1fd40a228fc8bae385e448c7e32a6ae134e43cf13bbc23f902b7"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ec6fbded0c61afe6f84e3c2a43e6d656791d95747d6d28b73eff1af64108c434"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:bfda6ee8990997a9df95c5606f3096dae65f09af7ca03a1e9ca28f088caca5cf"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b77f9f9cee87cd798f0fe26b7024344d1b03a7cd2d2cba7035f8433b13986325"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e02d3b96f2d0e4bab9ceaa30f37d4f75571e40c6272e95364bff3125a64d184"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1da38070738da53556a4b35ab67c1b9884a5dd48fa2f243db35dc14079ea3d0c"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ace43b26d88a58dcff16c20d23ff72b04d0a415f64d2820f4ff06b1166f50557"}, - {file = "grpcio_tools-1.62.3-cp37-cp37m-win_amd64.whl", hash = "sha256:350a80485e302daaa95d335a931f97b693e170e02d43767ab06552c708808950"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:c3a1ac9d394f8e229eb28eec2e04b9a6f5433fa19c9d32f1cb6066e3c5114a1d"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:11f363570dea661dde99e04a51bd108a5807b5df32a6f8bdf4860e34e94a4dbf"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9ad9950119d8ae27634e68b7663cc8d340ae535a0f80d85a55e56a6973ab1f"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c5d22b252dcef11dd1e0fbbe5bbfb9b4ae048e8880d33338215e8ccbdb03edc"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:27cd9ef5c5d68d5ed104b6dcb96fe9c66b82050e546c9e255716903c3d8f0373"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f4b1615adf67bd8bb71f3464146a6f9949972d06d21a4f5e87e73f6464d97f57"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-win32.whl", hash = "sha256:e18e15287c31baf574fcdf8251fb7f997d64e96c6ecf467906e576da0a079af6"}, - {file = "grpcio_tools-1.62.3-cp38-cp38-win_amd64.whl", hash = "sha256:6c3064610826f50bd69410c63101954676edc703e03f9e8f978a135f1aaf97c1"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:8e62cc7164b0b7c5128e637e394eb2ef3db0e61fc798e80c301de3b2379203ed"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:c8ad5cce554e2fcaf8842dee5d9462583b601a3a78f8b76a153c38c963f58c10"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec279dcf3518201fc592c65002754f58a6b542798cd7f3ecd4af086422f33f29"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c989246c2aebc13253f08be32538a4039a64e12d9c18f6d662d7aee641dc8b5"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca4f5eeadbb57cf03317d6a2857823239a63a59cc935f5bd6cf6e8b7af7a7ecc"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0cb3a3436ac119cbd37a7d3331d9bdf85dad21a6ac233a3411dff716dcbf401e"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-win32.whl", hash = "sha256:3eae6ea76d62fcac091e1f15c2dcedf1dc3f114f8df1a972a8a0745e89f4cf61"}, - {file = "grpcio_tools-1.62.3-cp39-cp39-win_amd64.whl", hash = "sha256:eec73a005443061f4759b71a056f745e3b000dc0dc125c9f20560232dfbcbd14"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:e0c71405399ef59782600b1f0bdebc69ba12d7c9527cd268162a86273971d294"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:df1a174a6f9d3b4c380f005f33352d2e95464f33f021fb08084735a2eb6e23b1"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7d789bfe53fce9e87aa80c3694a366258ce4c41b706258e9228ed4994832b780"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95c44a265ff01fd05166edae9350bc2e7d1d9a95e8f53b8cd04d2ae0a588c583"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b962a8767c3c0f9afe92e0dd6bb0b2305d35195a1053f84d4d31f585b87557ed"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d8616773126ec3cdf747b06a12e957b43ac15c34e4728def91fa67249a7c689a"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0067e79b6001560ac6acc78cca11fd3504fa27f8af46e3cdbac2f4998505e597"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-win32.whl", hash = "sha256:fa4f95a79a34afc3b5464895d091cd1911227fc3ab0441b9a37cd1817cf7db86"}, + {file = "grpcio_tools-1.66.1-cp310-cp310-win_amd64.whl", hash = "sha256:3acce426f5e643de63019311171f4d31131da8149de518716a95c29a2c12dd38"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:9a07e24feb7472419cf70ebbb38dd4299aea696f91f191b62a99b3ee9ff03f89"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:097a069e7c640043921ecaf3e88d7af78ccd40c25dbddc91db2a4a2adbd0393d"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:016fa273dc696c9d8045091ac50e000bce766183a6b150801f51c2946e33dbe3"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ec9f4f964f8e8ed5e9cc13deb678c83d5597074c256805373220627833bc5ad"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3198815814cdd12bdb69b7580d7770a4ad4c8b2093e0bd6b987bc817618e3eec"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:796620fc41d3fbb566d9614ef22bc55df67fac1f1e19c1e0fb6ec48bc9b6a44b"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:222d8dc218560698e1abf652fb47e4015994ec7a265ef46e012fd9c9e77a4d6b"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-win32.whl", hash = "sha256:56e17a11f34df252b4c6fb8aa8cd7b44d162dba9f3333be87ddf7c8bf496622a"}, + {file = "grpcio_tools-1.66.1-cp311-cp311-win_amd64.whl", hash = "sha256:edd52d667f2aa3c73233be0a821596937f24536647c12d96bfc54aa4cb04747d"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:869b6960d5daffda0dac1a474b44144f0dace0d4336394e499c4f400c5e2f8d9"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:68d9390bf9ba863ac147fc722d6548caa587235e887cac1bc2438212e89d1de7"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:b8660401beca7e3af28722439e07b0bcdca80b4a68f5a5a1138ae7b7780a6abf"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb67b9aa9cd69468bceb933e8e0f89fd13695746c018c4d2e6b3b84e73f3ad97"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5daceb9716e31edc0e1ba0f93303785211438c43502edddad7a919fc4cb3d664"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0a86398a4cd0665bc7f09fa90b89bac592c959d2c895bf3cf5d47a98c0f2d24c"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1b4acb53338072ab3023e418a5c7059cb15686abd1607516fa1453406dd5f69d"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-win32.whl", hash = "sha256:88e04b7546101bc79c868c941777efd5088063a9e4f03b4d7263dde796fbabf7"}, + {file = "grpcio_tools-1.66.1-cp312-cp312-win_amd64.whl", hash = "sha256:5b4fc56abeafae74140f5da29af1093e88ce64811d77f1a81c3146e9e996fb6a"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:d4dd2ff982c1aa328ef47ce34f07af82f1f13599912fb1618ebc5fe1e14dddb8"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:066648543f786cb74b1fef5652359952455dbba37e832642026fd9fd8a219b5f"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:d19d47744c30e6bafa76b3113740e71f382d75ebb2918c1efd62ebe6ba7e20f9"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:739c53571130b359b738ac7d6d0a1f772e15779b66df7e6764bee4071cd38689"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2226ff8d3ecba83b7622946df19d6e8e15cb52f761b8d9e2f807b228db5f1b1e"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f4b1498cb8b422fbae32a491c9154e8d47650caf5852fbe6b3b34253e824343"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:93d2d9e14e81affdc63d67c42eb16a8da1b6fecc16442a703ca60eb0e7591691"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-win32.whl", hash = "sha256:d761dfd97a10e4aae73628b5120c64e56f0cded88651d0003d2d80e678c3e7c9"}, + {file = "grpcio_tools-1.66.1-cp38-cp38-win_amd64.whl", hash = "sha256:e1c2ac0955f5fb87b8444316e475242d194c3f3cd0b7b6e54b889a7b6f05156f"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:5f1f04578b72c281e39274348a61d240c48d5321ba8d7a8838e194099ecbc322"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:da9b0c08dbbf07535ee1b75a22d0acc5675a808a3a3df9f9b21e0e73ddfbb3a9"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:e302b4e1fa856d74ff65c65888b3a37153287ce6ad5bad80b2fdf95130accec2"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fc3f62494f238774755ff90f0e66a93ac7972ea1eb7180c45acf4fd53b25cca"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cad65ff22459aa387f543d293f54834c9aac8f76fb7416a7046556df75b567"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3d17a27c567a5e4d18f487368215cb51b43e2499059fd6113b92f7ae1fee48be"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4df167e67b083f96bc277032a526f6186e98662aaa49baea1dfb8ecfe26ce117"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-win32.whl", hash = "sha256:f94d5193b2f2a9595795b83e7978b2bee1c0399da66f2f24d179c388f81fb99c"}, + {file = "grpcio_tools-1.66.1-cp39-cp39-win_amd64.whl", hash = "sha256:66f527a1e3f063065e29cf6f3e55892434d13a5a51e3b22402e09da9521e98a3"}, + {file = "grpcio_tools-1.66.1.tar.gz", hash = "sha256:5055ffe840ea8f505c30378be02afb4dbecb33480e554debe10b63d6b2f641c3"}, ] [package.dependencies] -grpcio = ">=1.62.3" -protobuf = ">=4.21.6,<5.0dev" +grpcio = ">=1.66.1" +protobuf = ">=5.26.1,<6.0dev" setuptools = "*" [[package]] @@ -615,22 +616,22 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "protobuf" -version = "4.25.4" +version = "5.28.0" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"}, - {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"}, - {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"}, - {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"}, - {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"}, - {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"}, - {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"}, - {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"}, - {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"}, + {file = "protobuf-5.28.0-cp310-abi3-win32.whl", hash = "sha256:66c3edeedb774a3508ae70d87b3a19786445fe9a068dd3585e0cefa8a77b83d0"}, + {file = "protobuf-5.28.0-cp310-abi3-win_amd64.whl", hash = "sha256:6d7cc9e60f976cf3e873acb9a40fed04afb5d224608ed5c1a105db4a3f09c5b6"}, + {file = "protobuf-5.28.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:532627e8fdd825cf8767a2d2b94d77e874d5ddb0adefb04b237f7cc296748681"}, + {file = "protobuf-5.28.0-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:018db9056b9d75eb93d12a9d35120f97a84d9a919bcab11ed56ad2d399d6e8dd"}, + {file = "protobuf-5.28.0-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:6206afcb2d90181ae8722798dcb56dc76675ab67458ac24c0dd7d75d632ac9bd"}, + {file = "protobuf-5.28.0-cp38-cp38-win32.whl", hash = "sha256:eef7a8a2f4318e2cb2dee8666d26e58eaf437c14788f3a2911d0c3da40405ae8"}, + {file = "protobuf-5.28.0-cp38-cp38-win_amd64.whl", hash = "sha256:d001a73c8bc2bf5b5c1360d59dd7573744e163b3607fa92788b7f3d5fefbd9a5"}, + {file = "protobuf-5.28.0-cp39-cp39-win32.whl", hash = "sha256:dde9fcaa24e7a9654f4baf2a55250b13a5ea701493d904c54069776b99a8216b"}, + {file = "protobuf-5.28.0-cp39-cp39-win_amd64.whl", hash = "sha256:853db610214e77ee817ecf0514e0d1d052dff7f63a0c157aa6eabae98db8a8de"}, + {file = "protobuf-5.28.0-py3-none-any.whl", hash = "sha256:510ed78cd0980f6d3218099e874714cdf0d8a95582e7b059b06cabad855ed0a0"}, + {file = "protobuf-5.28.0.tar.gz", hash = "sha256:dde74af0fa774fa98892209992295adbfb91da3fa98c8f67a88afe8f5a349add"}, ] [[package]] @@ -809,17 +810,17 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments [[package]] name = "pytest-asyncio" -version = "0.23.8" +version = "0.24.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, - {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, + {file = "pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b"}, + {file = "pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276"}, ] [package.dependencies] -pytest = ">=7.0.0,<9" +pytest = ">=8.2,<9" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -917,13 +918,13 @@ files = [ [[package]] name = "setuptools" -version = "74.1.1" +version = "74.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-74.1.1-py3-none-any.whl", hash = "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766"}, - {file = "setuptools-74.1.1.tar.gz", hash = "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847"}, + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, ] [package.extras] @@ -1016,103 +1017,103 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [[package]] name = "yarl" -version = "1.9.8" +version = "1.9.11" description = "Yet another URL library" optional = false python-versions = ">=3.8" files = [ - {file = "yarl-1.9.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:08359dbc3540fafa8972db45d3ef2d61370b4c24b8a028a4301bc5d076eee0e2"}, - {file = "yarl-1.9.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7a716aae4fcecadfe4648268d3c194315152715391f4af6fad50d502be122e9"}, - {file = "yarl-1.9.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:62223670042a219b8e6fbd2c7f35c456278dcd346d3aba3f2c01c9bdec28f37e"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18097a9e50ea31c61fece83bac8f63263f0c0c16c439bf82ac729c23f3b170e3"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5809f8a48c8dab91f708947d358271ef1890c3012d6c45719f49d04af2112057"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71ff7a22355241f89e850afbc8858fb671ba7e2763af32ebbea158d23a84902a"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d54e9880e781a490483200a74f6314fb6cf692a8197ccde93adf32bec95626b"}, - {file = "yarl-1.9.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ad8ea6ab27e27821739dfb94fab63284e3a52055e268f04529dc082fd0d59a2"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b79e031524259b51cdd1ea41f5053491ad3565b9cecd76389c9f705752d14283"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bd91ccded75d080f13ed01a5f5796887916d2e8c0999cd68bcb58f89f9b1c29c"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:583f48ab25b3906e3716479e8f700c4cc487e44d52766a4ea52b01cb7ea772d6"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2f3e89838acdaf5bbd69383c408d9e119b4e9efbe8a38fa40045b5c966f918e3"}, - {file = "yarl-1.9.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a44c0b83d1871e1e1859167a1804143f590f86ac4708380852dca4d8299d8594"}, - {file = "yarl-1.9.8-cp310-cp310-win32.whl", hash = "sha256:5d39ae58a67b64b470021d18a13529d0c58efc5bf057936ec4b29092d4061030"}, - {file = "yarl-1.9.8-cp310-cp310-win_amd64.whl", hash = "sha256:f89ade31926b9931bbe29f5c62d4174057e532fb0c72e2e6abdd129fda6a60f3"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:986296e65b0312c1da168de4ec1bb054b4a7b0ec26e3f9e8dafc06bbb1385030"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b4c7c015dc813aa5fe15379f3540d178e3743c0f1cf9e4a4a8bff94bd2832a4d"}, - {file = "yarl-1.9.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:22b2db22f72e1cb8a552ae12dfb748167153c7cbf353c62781915b5328bf2561"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a567416bfb2a2b093aa64685aa7b6dfb593888784ef91b16fa6b985cceb951"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:178f4ab054f3a5dc84c8091bd7395b6713aac83af893b62259d5eb3f5359ce7f"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:02fe9809b29a7dc4a27b769a43c556288d949205db54338871a122b64751e0f4"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c885a81f6c89b0d45fc0dd88e005c77dd8ba1dac421466d0dbb9192ce6d34e1e"}, - {file = "yarl-1.9.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99f78f45c8b4c9824e1a37eb0a3ae63ad2dff66434d9620265a4256088be9cda"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:30929a10be9a13026fd68377aba3223d633370abb93dadd3932754f3dcf4734a"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ee7c00a1979b3f23c8094dce6d9875453b3cb91b1153d9efaefa6773cf80cdb0"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e89d76b2aa11287f038a37577528c5f62d9385020b795a011f60dfd1b217cf9f"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:81fde88456d2cbe005e16aca78ef744f322b3b15184dfe41b5b04f97b46aa5be"}, - {file = "yarl-1.9.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b3dca0a4e192207f8bb4057725ff95e9a14d53a04728742f2b03692fc91b0a43"}, - {file = "yarl-1.9.8-cp311-cp311-win32.whl", hash = "sha256:9ea3a8532ea9fc2eeb6fc3def0c341aaeab7625545844f9c0a15350c17f9f479"}, - {file = "yarl-1.9.8-cp311-cp311-win_amd64.whl", hash = "sha256:c810606719683f4ab92127712efe283674d6ed29a627374411c762852913c2dd"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b3d373373908e687aa4c8b0666870b0cf65605254ba0819ed8d5af2fc0780496"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e3d1be58e28825a14fb9561733de62fbe95c892febe7d7a9ebcde916c531d603"}, - {file = "yarl-1.9.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7318736a8ee9de8217d590866dd716fa3c0895e684e2ec6152d945a4ab758043"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db3dd602cbf6613dc1e4a6fbde7a1bee86948e5940086090bb505c2ab959bbdf"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5950226b128a1610f57c1f756fc611fdbdcb1e6b4497ccb05fce76a38915b07"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b341a995673180ed81a1040228a59e0b47ee687e367b1a03d829fa3c0eb4607e"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f912153a34698994f32cf683d966014b0dd99c73481302d6159bcb3a8303e84"}, - {file = "yarl-1.9.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ceab2b16043ae1953863ec240eb918ba1ac40d2aad55225141aac288c606442"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c0d2bc2646ae2380bb91b9ddc2eb1e1fa6baef128499e817134d1d50c8b6c56"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ebd98e16ff9948e4d31514c937275017a122b765cb89961dd5d44ecd2cc18140"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:83273ca458c85d7b026c770a86df6e36349e85100bd2cefe6d0ad7167a8f12a6"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4511dd73b6aeda0cc39111839923f1545726d621813c9d13355824fba328dbcf"}, - {file = "yarl-1.9.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ffb9f1cad56c547aa127e2c315e666ee9838156c8a3b14f37ba545b0167aa5e"}, - {file = "yarl-1.9.8-cp312-cp312-win32.whl", hash = "sha256:5796358c3d6c72b108b570e20ab951463237ec473b6d204da21050feaaaf7dca"}, - {file = "yarl-1.9.8-cp312-cp312-win_amd64.whl", hash = "sha256:c2dc6e941bf53160b44858d1b24767a056cd83166b69fbdd3b2e401856d8932e"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cb3d488f049db9522e3a0de50e07bac0c53565acd88a07bc9cf7182fd6890307"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:50cbf73b6a4b62c3ad633e8920f2791adf485356ef37c9edbd5a1e7de8da2ddc"}, - {file = "yarl-1.9.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1e0649ee7ac354a3e40ee849707140b14a2cd0cd2dc2062fe620458dfe465c8"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2501b230e89cad2361719860648f780197812d3be91c7ca6658a097a7e22fc4"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be441a73f9f49427906274008bd98384d8ca4655981735281c314fc7c145d256"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7de1968a1c2690b86e32e91acf8ed2043c346293f9bbe1704b9f6a481b73bd11"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce892a75a2209cf4f7007de21c6f6d607f4b9406ac613a59ad02340f6e933e4"}, - {file = "yarl-1.9.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:405e75bb94b87cc4167eef0e08d6a539f60633229f7043edc2e65c82ef80e874"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5811c1906b38f2a203df1266c6dd11680ca85d610d6ee3701dde262a305520"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:51476f19fe1296d3efe3770179548f5f4822e5c4ead9f5160ba156a6a9f5272c"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2af144a81883db914636bec646da4dcccfe9db05c2899e7afe90a3d817ffce"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:8c91b71b0af1fb5454709e34b39e38c975faaa89c0cc8bb744d60300ca710fcd"}, - {file = "yarl-1.9.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a562055b5ec6371c307320e8460d16675244e810b20f343371fc52797d23615"}, - {file = "yarl-1.9.8-cp313-cp313-win32.whl", hash = "sha256:f7442a9342aa04ea60b760a8f0d210e269f881eb0660a2000fa1f8cb89820931"}, - {file = "yarl-1.9.8-cp313-cp313-win_amd64.whl", hash = "sha256:21ef75d8a18fa47725b50fcb7ae6d23a51c71a7426cdf7097e52f9e12a995eb6"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd9affa8c18198dfa5a19c63b29ef2a2f35b8efacaf0bdd3e58f974c0ab0108d"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f79e65f16413a95d9f7633802a2ee34730b3ba1dd0af82811b377057883c4fb7"}, - {file = "yarl-1.9.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3f8c454cf7e4d3762515ed2b5a40cf2feaeb8a8ed1d121f131a6178e16015319"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f972fc63a1d6165d1cff650a16a498b0087334f7f9cd7385860c086d009cd49"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ac4aa2f2d8253b9a5455d5f0ed45687ea9715b78a563490ddf7954337974cb7"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b001379047de5e03224dc0592f1b0e60738857a9b992d9b636b5050500ecce23"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39deb5a67b591682e54d1b09b36e79cd608ca27bea1fefed3bcaaa0b05d2b25e"}, - {file = "yarl-1.9.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffd9dd7eac5d36f53fccdf11e98730b7a628561c77f6c2a9e0909d2a304f34d1"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:497d5fd7dce44b5dcac648c830c99a673d30bc6cd9905b3e255c92c6dc01f537"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d99011d564f2b5cb4cf1012f9058e08d8d79674332474f7e940131f5952015df"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:600f734296cb99db1af7e34c0dcf8ec9477072f72c4621677637fdc2273af120"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6703deac7bb0dd8b3f0bc3cb6844dab4e74c85c70783ae89bd0b52286ebdc102"}, - {file = "yarl-1.9.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3346e2f641fcf31cf32c5a394d625e0676aba6fadccc06d35435e475753ed05d"}, - {file = "yarl-1.9.8-cp38-cp38-win32.whl", hash = "sha256:a54f7a63e48156a77a7c0333cefed29ceb004ab683d685a1192b341ac445cb73"}, - {file = "yarl-1.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:45992ff8d941a1901c35f2ed90a60cb5fee8705ffadff395db4a5fd164473542"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:590437f092af08e71521cc302940ef897e969152434c825bb3fb8f308b63a8bb"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:551c26789acd38c7b90a89a1f262291d9f9a6a677185a83b5781e2a2c4258aec"}, - {file = "yarl-1.9.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:121bf7d647b3f6481ce1030350c1cc4c43e18758010732a449c71a1784ae793d"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9db466370e8bc3459912850494ad3401f3664ff3a56842f0d4514166f54c9f"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff56e21379824f3e3c39a37083d5ab905168b9483b1c0c563dd92eb2db18b251"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cce910a1510d60c7eff4bb263b28b9afdcc5f6b85c555e492cfe7548a09e2476"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ba7c4b50cc0bb4caaa54554613ca13db47a24878a4fc1063e6303494fc67567"}, - {file = "yarl-1.9.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b345de5e725b82e9458dc1381d7e28fe7d7ef93491370461dc98283b9dda51e2"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:49dd58b79b0fd04e880c90bc570fde68407cc516c58812f0321f5e74c131107c"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:15fb127bcc19065fd912391a43bc80114635f0062e0465765633ab5d0c7fc3a1"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6f4f87a7c97ba77fdc764b893ae4083c74e5857904962a70025ade0cd42bdbaf"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d336601d9ff3dc3b12263739ab1add25bdd2345d675f59ad49f72d9a6ccbc865"}, - {file = "yarl-1.9.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3574834e4aaf24e24d12fa4fd53d0b0fd1d70b24a67bed81c44b284377e81d45"}, - {file = "yarl-1.9.8-cp39-cp39-win32.whl", hash = "sha256:db9305328486539bb7182c15f1ad1ea95dae52245e93a049f2b1d6f04e63674d"}, - {file = "yarl-1.9.8-cp39-cp39-win_amd64.whl", hash = "sha256:588d62a57c7a43b230557728ec9f252b3f81ad073cb5c0ef48d87cd3f8b6ace2"}, - {file = "yarl-1.9.8-py3-none-any.whl", hash = "sha256:d1612ce50f23b94897b9ef5eb65b72398a9a83ea990b42825272590f3484dae3"}, - {file = "yarl-1.9.8.tar.gz", hash = "sha256:3089553548d9ab23152cecb5a71131caaa9e9b16d7fc8196057c374fdc53cc4b"}, + {file = "yarl-1.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:79e08c691deae6fcac2fdde2e0515ac561dd3630d7c8adf7b1e786e22f1e193b"}, + {file = "yarl-1.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:752f4b5cf93268dc73c2ae994cc6d684b0dad5118bc87fbd965fd5d6dca20f45"}, + {file = "yarl-1.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:441049d3a449fb8756b0535be72c6a1a532938a33e1cf03523076700a5f87a01"}, + {file = "yarl-1.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3dfe17b4aed832c627319da22a33f27f282bd32633d6b145c726d519c89fbaf"}, + {file = "yarl-1.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67abcb7df27952864440c9c85f1c549a4ad94afe44e2655f77d74b0d25895454"}, + {file = "yarl-1.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6de3fa29e76fd1518a80e6af4902c44f3b1b4d7fed28eb06913bba4727443de3"}, + {file = "yarl-1.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fee45b3bd4d8d5786472e056aa1359cc4dc9da68aded95a10cd7929a0ec661fe"}, + {file = "yarl-1.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c59b23886234abeba62087fd97d10fb6b905d9e36e2f3465d1886ce5c0ca30df"}, + {file = "yarl-1.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d93c612b2024ac25a3dc01341fd98fdd19c8c5e2011f3dcd084b3743cba8d756"}, + {file = "yarl-1.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4d368e3b9ecd50fa22017a20c49e356471af6ae91c4d788c6e9297e25ddf5a62"}, + {file = "yarl-1.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5b593acd45cdd4cf6664d342ceacedf25cd95263b83b964fddd6c78930ea5211"}, + {file = "yarl-1.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:224f8186c220ff00079e64bf193909829144d4e5174bb58665ef0da8bf6955c4"}, + {file = "yarl-1.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:91c478741d7563a12162f7a2db96c0d23d93b0521563f1f1f0ece46ea1702d33"}, + {file = "yarl-1.9.11-cp310-cp310-win32.whl", hash = "sha256:1cdb8f5bb0534986776a43df84031da7ff04ac0cf87cb22ae8a6368231949c40"}, + {file = "yarl-1.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:498439af143b43a2b2314451ffd0295410aa0dcbdac5ee18fc8633da4670b605"}, + {file = "yarl-1.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e290de5db4fd4859b4ed57cddfe793fcb218504e65781854a8ac283ab8d5518"}, + {file = "yarl-1.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e5f50a2e26cc2b89186f04c97e0ec0ba107ae41f1262ad16832d46849864f914"}, + {file = "yarl-1.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b4a0e724a28d7447e4d549c8f40779f90e20147e94bf949d490402eee09845c6"}, + {file = "yarl-1.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85333d38a4fa5997fa2ff6fd169be66626d814b34fa35ec669e8c914ca50a097"}, + {file = "yarl-1.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ff184002ee72e4b247240e35d5dce4c2d9a0e81fdbef715dde79ab4718aa541"}, + {file = "yarl-1.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:675004040f847c0284827f44a1fa92d8baf425632cc93e7e0aa38408774b07c1"}, + {file = "yarl-1.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30703a7ade2b53f02e09a30685b70cd54f65ed314a8d9af08670c9a5391af1b"}, + {file = "yarl-1.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7230007ab67d43cf19200ec15bc6b654e6b85c402f545a6fc565d254d34ff754"}, + {file = "yarl-1.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8c2cf0c7ad745e1c6530fe6521dfb19ca43338239dfcc7da165d0ef2332c0882"}, + {file = "yarl-1.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4567cc08f479ad80fb07ed0c9e1bcb363a4f6e3483a490a39d57d1419bf1c4c7"}, + {file = "yarl-1.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:95adc179a02949c4560ef40f8f650a008380766eb253d74232eb9c024747c111"}, + {file = "yarl-1.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:755ae9cff06c429632d750aa8206f08df2e3d422ca67be79567aadbe74ae64cc"}, + {file = "yarl-1.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:94f71d54c5faf715e92c8434b4a0b968c4d1043469954d228fc031d51086f143"}, + {file = "yarl-1.9.11-cp311-cp311-win32.whl", hash = "sha256:4ae079573efeaa54e5978ce86b77f4175cd32f42afcaf9bfb8a0677e91f84e4e"}, + {file = "yarl-1.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:9fae7ec5c9a4fe22abb995804e6ce87067dfaf7e940272b79328ce37c8f22097"}, + {file = "yarl-1.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:614fa50fd0db41b79f426939a413d216cdc7bab8d8c8a25844798d286a999c5a"}, + {file = "yarl-1.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ff64f575d71eacb5a4d6f0696bfe991993d979423ea2241f23ab19ff63f0f9d1"}, + {file = "yarl-1.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c23f6dc3d7126b4c64b80aa186ac2bb65ab104a8372c4454e462fb074197bc6"}, + {file = "yarl-1.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8f847cc092c2b85d22e527f91ea83a6cf51533e727e2461557a47a859f96734"}, + {file = "yarl-1.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63a5dc2866791236779d99d7a422611d22bb3a3d50935bafa4e017ea13e51469"}, + {file = "yarl-1.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c335342d482e66254ae94b1231b1532790afb754f89e2e0c646f7f19d09740aa"}, + {file = "yarl-1.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4a8c3dedd081cca134a21179aebe58b6e426e8d1e0202da9d1cafa56e01af3c"}, + {file = "yarl-1.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:504d19320c92532cabc3495fb7ed6bb599f3c2bfb45fed432049bf4693dbd6d0"}, + {file = "yarl-1.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b2a8e5eb18181060197e3d5db7e78f818432725c0759bc1e5a9d603d9246389"}, + {file = "yarl-1.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f568d70b7187f4002b6b500c0996c37674a25ce44b20716faebe5fdb8bd356e7"}, + {file = "yarl-1.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:735b285ea46ca7e86ad261a462a071d0968aade44e1a3ea2b7d4f3d63b5aab12"}, + {file = "yarl-1.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2d1c81c3b92bef0c1c180048e43a5a85754a61b4f69d6f84df8e4bd615bef25d"}, + {file = "yarl-1.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8d6e1c1562b53bd26efd38e886fc13863b8d904d559426777990171020c478a9"}, + {file = "yarl-1.9.11-cp312-cp312-win32.whl", hash = "sha256:aeba4aaa59cb709edb824fa88a27cbbff4e0095aaf77212b652989276c493c00"}, + {file = "yarl-1.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:569309a3efb8369ff5d32edb2a0520ebaf810c3059f11d34477418c90aa878fd"}, + {file = "yarl-1.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:4915818ac850c3b0413e953af34398775b7a337babe1e4d15f68c8f5c4872553"}, + {file = "yarl-1.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ef9610b2f5a73707d4d8bac040f0115ca848e510e3b1f45ca53e97f609b54130"}, + {file = "yarl-1.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47c0a3dc8076a8dd159de10628dea04215bc7ddaa46c5775bf96066a0a18f82b"}, + {file = "yarl-1.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:545f2fbfa0c723b446e9298b5beba0999ff82ce2c126110759e8dac29b5deaf4"}, + {file = "yarl-1.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9137975a4ccc163ad5d7a75aad966e6e4e95dedee08d7995eab896a639a0bce2"}, + {file = "yarl-1.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0b0c70c451d2a86f8408abced5b7498423e2487543acf6fcf618b03f6e669b0a"}, + {file = "yarl-1.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce2bd986b1e44528677c237b74d59f215c8bfcdf2d69442aa10f62fd6ab2951c"}, + {file = "yarl-1.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d7b717f77846a9631046899c6cc730ea469c0e2fb252ccff1cc119950dbc296"}, + {file = "yarl-1.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3a26a24bbd19241283d601173cea1e5b93dec361a223394e18a1e8e5b0ef20bd"}, + {file = "yarl-1.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c189bf01af155ac9882e128d9f3b3ad68a1f2c2f51404afad7201305df4e12b1"}, + {file = "yarl-1.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0cbcc2c54084b2bda4109415631db017cf2960f74f9e8fd1698e1400e4f8aae2"}, + {file = "yarl-1.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:30f201bc65941a4aa59c1236783efe89049ec5549dafc8cd2b63cc179d3767b0"}, + {file = "yarl-1.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:922ba3b74f0958a0b5b9c14ff1ef12714a381760c08018f2b9827632783a590c"}, + {file = "yarl-1.9.11-cp313-cp313-win32.whl", hash = "sha256:17107b4b8c43e66befdcbe543fff2f9c93f7a3a9f8e3a9c9ac42bffeba0e8828"}, + {file = "yarl-1.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:0324506afab4f2e176a93cb08b8abcb8b009e1f324e6cbced999a8f5dd9ddb76"}, + {file = "yarl-1.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4e4f820fde9437bb47297194f43d29086433e6467fa28fe9876366ad357bd7bb"}, + {file = "yarl-1.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dfa9b9d5c9c0dbe69670f5695264452f5e40947590ec3a38cfddc9640ae8ff89"}, + {file = "yarl-1.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e700eb26635ce665c018c8cfea058baff9b843ed0cc77aa61849d807bb82a64c"}, + {file = "yarl-1.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c305c1bdf10869b5e51facf50bd5b15892884aeae81962ae4ba061fc11217103"}, + {file = "yarl-1.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5b7b307140231ea4f7aad5b69355aba2a67f2d7bc34271cffa3c9c324d35b27"}, + {file = "yarl-1.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a744bdeda6c86cf3025c94eb0e01ccabe949cf385cd75b6576a3ac9669404b68"}, + {file = "yarl-1.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8ed183c7a8f75e40068333fc185566472a8f6c77a750cf7541e11810576ea5"}, + {file = "yarl-1.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1db9a4384694b5d20bdd9cb53f033b0831ac816416ab176c8d0997835015d22"}, + {file = "yarl-1.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:70194da6e99713250aa3f335a7fa246b36adf53672a2bcd0ddaa375d04e53dc0"}, + {file = "yarl-1.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ddad5cfcda729e22422bb1c85520bdf2770ce6d975600573ac9017fe882f4b7e"}, + {file = "yarl-1.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ca35996e0a4bed28fa0640d9512d37952f6b50dea583bcc167d4f0b1e112ac7f"}, + {file = "yarl-1.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:61ec0e80970b21a8f3c4b97fa6c6d181c6c6a135dbc7b4a601a78add3feeb209"}, + {file = "yarl-1.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9636e4519f6c7558fdccf8f91e6e3b98df2340dc505c4cc3286986d33f2096c2"}, + {file = "yarl-1.9.11-cp38-cp38-win32.whl", hash = "sha256:58081cea14b8feda57c7ce447520e9d0a96c4d010cce54373d789c13242d7083"}, + {file = "yarl-1.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:7d2dee7d6485807c0f64dd5eab9262b7c0b34f760e502243dd83ec09d647d5e1"}, + {file = "yarl-1.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d65ad67f981e93ea11f87815f67d086c4f33da4800cf2106d650dd8a0b79dda4"}, + {file = "yarl-1.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:752c0d33b4aacdb147871d0754b88f53922c6dc2aff033096516b3d5f0c02a0f"}, + {file = "yarl-1.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:54cc24be98d7f4ff355ca2e725a577e19909788c0db6beead67a0dda70bd3f82"}, + {file = "yarl-1.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c82126817492bb2ebc946e74af1ffa10aacaca81bee360858477f96124be39a"}, + {file = "yarl-1.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8503989860d7ac10c85cb5b607fec003a45049cf7a5b4b72451e87893c6bb990"}, + {file = "yarl-1.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:475e09a67f8b09720192a170ad9021b7abf7827ffd4f3a83826317a705be06b7"}, + {file = "yarl-1.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afcac5bda602b74ff701e1f683feccd8cce0d5a21dbc68db81bf9bd8fd93ba56"}, + {file = "yarl-1.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaeffcb84faceb2923a94a8a9aaa972745d3c728ab54dd011530cc30a3d5d0c1"}, + {file = "yarl-1.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:51a6f770ac86477cd5c553f88a77a06fe1f6f3b643b053fcc7902ab55d6cbe14"}, + {file = "yarl-1.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3fcd056cb7dff3aea5b1ee1b425b0fbaa2fbf6a1c6003e88caf524f01de5f395"}, + {file = "yarl-1.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:21e56c30e39a1833e4e3fd0112dde98c2abcbc4c39b077e6105c76bb63d2aa04"}, + {file = "yarl-1.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0a205ec6349879f5e75dddfb63e069a24f726df5330b92ce76c4752a436aac01"}, + {file = "yarl-1.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5706821e1cf3c70dfea223e4e0958ea354f4e2af9420a1bd45c6b547297fb97"}, + {file = "yarl-1.9.11-cp39-cp39-win32.whl", hash = "sha256:cc295969f8c2172b5d013c0871dccfec7a0e1186cf961e7ea575d47b4d5cbd32"}, + {file = "yarl-1.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:55a67dd29367ce7c08a0541bb602ec0a2c10d46c86b94830a1a665f7fd093dfa"}, + {file = "yarl-1.9.11-py3-none-any.whl", hash = "sha256:c6f6c87665a9e18a635f0545ea541d9640617832af2317d4f5ad389686b4ed3d"}, + {file = "yarl-1.9.11.tar.gz", hash = "sha256:c7548a90cb72b67652e2cd6ae80e2683ee08fde663104528ac7df12d8ef271d2"}, ] [package.dependencies] @@ -1122,4 +1123,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "5d671d0baa7967dc5734f951173cdab02e63e414b490c9ddafd34d7cd7c6ff3e" +content-hash = "2c39dc75940a8d96c5830b284ca57427f0e679225fb0f4a149e75a19048428a0" diff --git a/pyproject.toml b/pyproject.toml index dfe70318..dff762d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,25 +7,25 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.10" -grpcio = "^1.64.1" -python-dotenv = "^1.0.0" -protobuf = "^4.25.2" -pyyaml = "^6.0.1" -grpcio-tools = "^1.60.0" -loguru = "^0.7.2" -pydantic = "^2.6.3" -python-dateutil = "^2.9.0.post0" +grpcio = "~=1.66.1" +python-dotenv = "~=1.0.1" +protobuf = "~=5.28.0" +pyyaml = "~=6.0.2" +grpcio-tools = "~=1.66.1" +loguru = "~=0.7.2" +pydantic = "~=2.8.2" +python-dateutil = "~=2.9.0.post0" urllib3 = ">=1.26.20" -aiostream = "^0.5.2" -nest-asyncio = "^1.6.0" -aiohttp = "^3.10.5" -aiohttp-retry = "^2.8.3" +aiostream = "~=0.6.2" +nest-asyncio = "~=1.6.0" +aiohttp = "~=3.10.5" +aiohttp-retry = "~=2.8.3" tenacity = ">=8.4.1" [tool.poetry.group.dev.dependencies] -pytest = "^8.2.2" -pytest-asyncio = "^0.23.8" -psutil = "^6.0.0" +pytest = "~=8.3.2" +pytest-asyncio = "~=0.24.0" +psutil = "~=6.0.0" [build-system] requires = ["poetry-core"] From 4c99969ddfaf8d5a835c442ac6f55a79a3f7e1f8 Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:38:52 -0400 Subject: [PATCH 3/6] Update Workers to All Have Mains --- examples/cancellation/worker.py | 13 +++++++++---- examples/concurrency_limit_rr/worker.py | 13 +++++++++---- examples/delayed/worker.py | 13 +++++++++---- examples/manual_trigger/worker.py | 13 +++++++++---- examples/overrides/worker.py | 13 +++++++++---- examples/rate_limit/worker.py | 4 ++++ examples/sticky-workers/worker.py | 13 +++++++++---- 7 files changed, 58 insertions(+), 24 deletions(-) diff --git a/examples/cancellation/worker.py b/examples/cancellation/worker.py index b495e05d..ac599104 100644 --- a/examples/cancellation/worker.py +++ b/examples/cancellation/worker.py @@ -23,8 +23,13 @@ async def step1(self, context: Context): print("Cancelled") -workflow = CancelWorkflow() -worker = hatchet.worker("cancellation-worker", max_runs=4) -worker.register_workflow(workflow) +def main(): + workflow = CancelWorkflow() + worker = hatchet.worker("cancellation-worker", max_runs=4) + worker.register_workflow(workflow) -worker.start() + worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/concurrency_limit_rr/worker.py b/examples/concurrency_limit_rr/worker.py index be58ed81..d792c983 100644 --- a/examples/concurrency_limit_rr/worker.py +++ b/examples/concurrency_limit_rr/worker.py @@ -27,8 +27,13 @@ def step1(self, context): pass -workflow = ConcurrencyDemoWorkflowRR() -worker = hatchet.worker("concurrency-demo-worker-rr", max_runs=10) -worker.register_workflow(workflow) +def main(): + workflow = ConcurrencyDemoWorkflowRR() + worker = hatchet.worker("concurrency-demo-worker-rr", max_runs=10) + worker.register_workflow(workflow) -worker.start() + worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/delayed/worker.py b/examples/delayed/worker.py index 9e9197e2..94f9491d 100644 --- a/examples/delayed/worker.py +++ b/examples/delayed/worker.py @@ -32,8 +32,13 @@ def step1(self, context: Context): print(f"message \t {context.workflow_input()['message']}") -worker = hatchet.worker("delayed-worker", max_runs=4) -worker.register_workflow(PrintSchedule()) -worker.register_workflow(PrintPrinter()) +def main(): + worker = hatchet.worker("delayed-worker", max_runs=4) + worker.register_workflow(PrintSchedule()) + worker.register_workflow(PrintPrinter()) -worker.start() + worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/manual_trigger/worker.py b/examples/manual_trigger/worker.py index e4108dea..9cf75b0d 100644 --- a/examples/manual_trigger/worker.py +++ b/examples/manual_trigger/worker.py @@ -47,8 +47,13 @@ def step2(self, context): return {"step2": "data2"} -workflow = ManualTriggerWorkflow() -worker = hatchet.worker("manual-worker", max_runs=4) -worker.register_workflow(workflow) +def main(): + workflow = ManualTriggerWorkflow() + worker = hatchet.worker("manual-worker", max_runs=4) + worker.register_workflow(workflow) -worker.start() + worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/overrides/worker.py b/examples/overrides/worker.py index 86609df3..b0d73713 100644 --- a/examples/overrides/worker.py +++ b/examples/overrides/worker.py @@ -69,8 +69,13 @@ def step4(self, context: Context): } -workflow = OverridesWorkflow() -worker = hatchet.worker("overrides-worker") -worker.register_workflow(workflow) +def main(): + workflow = OverridesWorkflow() + worker = hatchet.worker("overrides-worker") + worker.register_workflow(workflow) -worker.start() + worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/rate_limit/worker.py b/examples/rate_limit/worker.py index d773b606..142c7639 100644 --- a/examples/rate_limit/worker.py +++ b/examples/rate_limit/worker.py @@ -24,3 +24,7 @@ def main(): worker.register_workflow(RateLimitWorkflow()) worker.start() + + +if __name__ == "__main__": + main() diff --git a/examples/sticky-workers/worker.py b/examples/sticky-workers/worker.py index 48921978..c972af6f 100644 --- a/examples/sticky-workers/worker.py +++ b/examples/sticky-workers/worker.py @@ -36,7 +36,12 @@ def child(self, context: Context): return {"worker": context.worker.id()} -worker = hatchet.worker("sticky-worker", max_runs=10) -worker.register_workflow(StickyWorkflow()) -worker.register_workflow(StickyChildWorkflow()) -worker.start() +def main(): + worker = hatchet.worker("sticky-worker", max_runs=10) + worker.register_workflow(StickyWorkflow()) + worker.register_workflow(StickyChildWorkflow()) + worker.start() + + +if __name__ == "__main__": + main() From bb3ed6e975dc9fcc46146afeb125fbeec59b796e Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:39:15 -0400 Subject: [PATCH 4/6] Correct Logic for Active Event Loop Fetching --- hatchet_sdk/utils/aio_utils.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hatchet_sdk/utils/aio_utils.py b/hatchet_sdk/utils/aio_utils.py index 80806951..1f856cab 100644 --- a/hatchet_sdk/utils/aio_utils.py +++ b/hatchet_sdk/utils/aio_utils.py @@ -120,12 +120,18 @@ def get_active_event_loop(should_raise=True) -> asyncio.AbstractEventLoop | None event loop in the current thread. """ try: - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() patch_exception_handler(loop) return loop except RuntimeError as e: if ( - str(e).startswith("There is no current event loop in thread") + any( + substring in str(e) + for substring in [ + "There is no current event loop in thread", + "no running event loop", + ] + ) and not should_raise ): return None From a334bf00a8e2f7d49858ff7ee278317431af72a9 Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:40:08 -0400 Subject: [PATCH 5/6] Refactor Action Listener to Use ProcessPool Instead of a Single Process --- hatchet_sdk/worker/action_listener_process.py | 13 +- hatchet_sdk/worker/worker.py | 133 ++++++++++-------- 2 files changed, 84 insertions(+), 62 deletions(-) diff --git a/hatchet_sdk/worker/action_listener_process.py b/hatchet_sdk/worker/action_listener_process.py index 0135aa69..16f9de1f 100644 --- a/hatchet_sdk/worker/action_listener_process.py +++ b/hatchet_sdk/worker/action_listener_process.py @@ -4,6 +4,7 @@ import time from dataclasses import dataclass, field from multiprocessing import Queue +from multiprocessing.synchronize import Event as EventClass from typing import Any, List, Mapping, Optional import grpc @@ -75,9 +76,7 @@ def __post_init__(self): patch_exception_handler(loop) loop.add_signal_handler(signal.SIGINT, noop_handler) loop.add_signal_handler(signal.SIGTERM, noop_handler) - loop.add_signal_handler( - signal.SIGQUIT, lambda: asyncio.create_task(self.exit_gracefully()) - ) + loop.add_signal_handler(signal.SIGQUIT, noop_handler) async def start(self, retry_attempt=0): if retry_attempt > 5: @@ -121,7 +120,7 @@ async def start_event_send_loop(self): event: ActionEvent = await self._get_event() if event == STOP_LOOP: logger.debug("stopping event send loop...") - break + return logger.debug(f"tx: event: {event.action.action_id}/{event.type}") asyncio.create_task(self.send_event(event)) @@ -250,6 +249,7 @@ async def cleanup(self): self.listener.cleanup() self.event_queue.put(STOP_LOOP) + await asyncio.sleep(1) async def exit_gracefully(self, skip_unregister=False): if self.killing: @@ -269,12 +269,13 @@ def exit_forcefully(self): logger.debug("forcefully closing listener...") -def worker_action_listener_process(*args, **kwargs): +def worker_action_listener_process(stop_event: EventClass, *args, **kwargs): async def run(): process = WorkerActionListenerProcess(*args, **kwargs) await process.start() # Keep the process running - while not process.killing: + while not stop_event.is_set(): await asyncio.sleep(0.1) + await process.exit_gracefully() asyncio.run(run()) diff --git a/hatchet_sdk/worker/worker.py b/hatchet_sdk/worker/worker.py index c0e962c7..fec6d250 100644 --- a/hatchet_sdk/worker/worker.py +++ b/hatchet_sdk/worker/worker.py @@ -3,9 +3,17 @@ import os import signal import sys +from concurrent.futures import ( + CancelledError, + Future, + ProcessPoolExecutor, + ThreadPoolExecutor, +) from dataclasses import dataclass, field from enum import Enum -from multiprocessing import Process, Queue +from multiprocessing.context import SpawnContext +from multiprocessing.managers import SyncManager +from multiprocessing.synchronize import Event as EventClass from typing import Any, Callable, Dict, Optional from hatchet_sdk.client import Client, new_client_raw @@ -48,15 +56,20 @@ class Worker: killing: bool = field(init=False, default=False) _status: WorkerStatus = field(init=False, default=WorkerStatus.INITIALIZED) - action_listener_process: Process = field(init=False, default=None) + action_listener_process: Future = field(init=False, default=None) + action_listener_process_cancel_signal: EventClass = field(init=False, default=None) action_listener_health_check: asyncio.Task = field(init=False, default=None) action_runner: WorkerActionRunLoopManager = field(init=False, default=None) - ctx = multiprocessing.get_context("spawn") - action_queue: Queue = field(init=False, default_factory=ctx.Queue) - event_queue: Queue = field(init=False, default_factory=ctx.Queue) + ctx: SpawnContext = field(init=False, default=None) + manager: SyncManager = field(init=False, default=None) + executor: ProcessPoolExecutor = field(init=False, default=None) + + action_queue: multiprocessing.Queue = field(init=False, default=None) + event_queue: multiprocessing.Queue = field(init=False, default=None) loop: asyncio.AbstractEventLoop = field(init=False, default=None) + created_loop: bool = field(init=False, default=False) def __post_init__(self): self.client = new_client_raw(self.config, self.debug) @@ -118,14 +131,13 @@ def setup_loop(self, loop: asyncio.AbstractEventLoop | None = None): return created_loop def start(self, options: WorkerStartOptions = WorkerStartOptions()): - created_loop = self.setup_loop(options.loop) + self.created_loop = self.setup_loop(options.loop) f = asyncio.run_coroutine_threadsafe( self.async_start(options, _from_start=True), self.loop ) # start the loop and wait until its closed - if created_loop: + if self.created_loop: self.loop.run_forever() - if self.handle_kill: sys.exit(0) return f @@ -137,6 +149,7 @@ async def async_start( _from_start: bool = False, ): main_pid = os.getpid() + print("foo") logger.info("------------------------------------------") logger.info("STARTING HATCHET...") logger.debug(f"worker runtime starting on PID: {main_pid}") @@ -153,6 +166,13 @@ async def async_start( if not _from_start: self.setup_loop(options.loop) + self.ctx = multiprocessing.get_context("spawn") + self.manager = self.ctx.Manager() + self.action_listener_process_cancel_signal = self.manager.Event() + self.action_queue = self.manager.Queue() + self.event_queue = self.manager.Queue() + self.executor = ProcessPoolExecutor(mp_context=self.ctx) + self.action_listener_process = self._start_listener() self.action_runner = self._run_action_runner() self.action_listener_health_check = self.loop.create_task( @@ -181,46 +201,42 @@ def _run_action_runner(self): def _start_listener(self): action_list = [str(key) for key in self.action_registry.keys()] try: - process = self.ctx.Process( - target=worker_action_listener_process, - args=( - self.name, - action_list, - self.max_runs, - self.config, - self.action_queue, - self.event_queue, - self.handle_kill, - self.client.debug, - self.labels, - ), + future = self.executor.submit( + worker_action_listener_process, + self.action_listener_process_cancel_signal, + self.name, + action_list, + self.max_runs, + self.config, + self.action_queue, + self.event_queue, + self.handle_kill, + self.client.debug, + self.labels, ) - process.start() - logger.debug(f"action listener starting on PID: {process.pid}") + logger.debug(f"action listener started: {future}") - return process + return future except Exception as e: logger.error(f"failed to start action listener: {e}") sys.exit(1) async def _check_listener_health(self): logger.debug("starting action listener health check...") - try: - while not self.killing: - if ( - self.action_listener_process is None - or not self.action_listener_process.is_alive() - ): - logger.debug("child action listener process killed...") - self._status = WorkerStatus.UNHEALTHY - if not self.killing: - self.loop.create_task(self.exit_gracefully()) - break - else: - self._status = WorkerStatus.HEALTHY - await asyncio.sleep(1) - except Exception as e: - logger.error(f"error checking listener health: {e}") + while not self.killing: + if ( + self.action_listener_process is None + or self.action_listener_process.done() + ): + print(self.action_listener_process.exception()) + logger.debug("child action listener process killed...") + self._status = WorkerStatus.UNHEALTHY + if not self.killing: + self.loop.create_task(self.exit_gracefully()) + break + else: + self._status = WorkerStatus.HEALTHY + await asyncio.sleep(1) ## Cleanup methods def _setup_signal_handlers(self): @@ -237,7 +253,7 @@ def _handle_force_quit_signal(self, signum, frame): logger.info("received SIGQUIT...") self.exit_forcefully() - async def close(self): + def close(self): logger.info(f"closing worker '{self.name}'...") self.killing = True # self.action_queue.close() @@ -246,7 +262,13 @@ async def close(self): if self.action_runner is not None: self.action_runner.cleanup() - await self.action_listener_health_check + def close_listener(self): + if self.action_listener_process and not self.action_listener_process.done(): + self.action_listener_process_cancel_signal.set() + try: + self.action_listener_process.result(timeout=60) + except CancelledError: + logger.debug("action listener error on close") async def exit_gracefully(self): logger.debug(f"gracefully stopping worker: {self.name}") @@ -257,15 +279,17 @@ async def exit_gracefully(self): self.killing = True await self.action_runner.wait_for_tasks() + with ThreadPoolExecutor() as pool: + await self.loop.run_in_executor(pool, self.close_listener) + await asyncio.sleep(1) + self.executor.shutdown(wait=False) await self.action_runner.exit_gracefully() - if self.action_listener_process and self.action_listener_process.is_alive(): - self.action_listener_process.kill() - - await self.close() + self.close() + await self.action_listener_health_check - if self.loop: + if self.created_loop: self.loop.stop() logger.info("👋") @@ -274,16 +298,13 @@ def exit_forcefully(self): self.killing = True logger.debug(f"forcefully stopping worker: {self.name}") - - self.close() - - if self.action_listener_process: - self.action_listener_process.kill() # Forcefully kill the process - + self.executor.shutdown(wait=False) + if self.created_loop: + self.loop.stop() logger.info("👋") - sys.exit( - 1 - ) # Exit immediately TODO - should we exit with 1 here, there may be other workers to cleanup + + # Exit immediately TODO - should we exit with 1 here, there may be other workers to cleanup + sys.exit(1) def register_on_worker(callable: HatchetCallable, worker: Worker): From d9ee1b8851281e5dcf392159a5c90f7d1ddfa038 Mon Sep 17 00:00:00 2001 From: srhinos <6531393+srhinos@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:41:24 -0400 Subject: [PATCH 6/6] Run in Thread Pool Executor --- hatchet_sdk/worker/runner/run_loop_manager.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hatchet_sdk/worker/runner/run_loop_manager.py b/hatchet_sdk/worker/runner/run_loop_manager.py index 39ea69e5..1d5ac2bc 100644 --- a/hatchet_sdk/worker/runner/run_loop_manager.py +++ b/hatchet_sdk/worker/runner/run_loop_manager.py @@ -1,4 +1,5 @@ import asyncio +import concurrent import logging from dataclasses import dataclass, field from multiprocessing import Queue @@ -85,7 +86,8 @@ async def _start_action_loop(self): logger.debug("action runner loop stopped") async def _get_action(self): - return await self.loop.run_in_executor(None, self.action_queue.get) + with concurrent.futures.ThreadPoolExecutor() as pool: + return await self.loop.run_in_executor(pool, self.action_queue.get) async def exit_gracefully(self): if self.killing: @@ -95,11 +97,6 @@ async def exit_gracefully(self): self.cleanup() - # Wait for 1 second to allow last calls to flush. These are calls which have been - # added to the event loop as callbacks to tasks, so we're not aware of them in the - # task list. - await asyncio.sleep(1) - def exit_forcefully(self): logger.info("forcefully exiting runner...") self.cleanup()