hatchet-sdk 1.18.1__py3-none-any.whl → 1.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hatchet-sdk might be problematic. Click here for more details.

Files changed (234) hide show
  1. hatchet_sdk/clients/dispatcher/action_listener.py +0 -1
  2. hatchet_sdk/clients/dispatcher/dispatcher.py +0 -30
  3. hatchet_sdk/hatchet.py +0 -20
  4. hatchet_sdk/opentelemetry/instrumentor.py +1 -27
  5. hatchet_sdk/runnables/action.py +2 -5
  6. hatchet_sdk/runnables/task.py +0 -1
  7. hatchet_sdk/utils/opentelemetry.py +0 -1
  8. hatchet_sdk/worker/action_listener_process.py +0 -29
  9. hatchet_sdk/worker/runner/runner.py +1 -105
  10. {hatchet_sdk-1.18.1.dist-info → hatchet_sdk-1.20.0.dist-info}/METADATA +2 -3
  11. {hatchet_sdk-1.18.1.dist-info → hatchet_sdk-1.20.0.dist-info}/RECORD +13 -234
  12. hatchet_sdk/v0/__init__.py +0 -251
  13. hatchet_sdk/v0/client.py +0 -119
  14. hatchet_sdk/v0/clients/admin.py +0 -541
  15. hatchet_sdk/v0/clients/dispatcher/action_listener.py +0 -422
  16. hatchet_sdk/v0/clients/dispatcher/dispatcher.py +0 -204
  17. hatchet_sdk/v0/clients/event_ts.py +0 -28
  18. hatchet_sdk/v0/clients/events.py +0 -182
  19. hatchet_sdk/v0/clients/rest/__init__.py +0 -307
  20. hatchet_sdk/v0/clients/rest/api/__init__.py +0 -19
  21. hatchet_sdk/v0/clients/rest/api/api_token_api.py +0 -858
  22. hatchet_sdk/v0/clients/rest/api/default_api.py +0 -2259
  23. hatchet_sdk/v0/clients/rest/api/event_api.py +0 -2548
  24. hatchet_sdk/v0/clients/rest/api/github_api.py +0 -331
  25. hatchet_sdk/v0/clients/rest/api/healthcheck_api.py +0 -483
  26. hatchet_sdk/v0/clients/rest/api/log_api.py +0 -449
  27. hatchet_sdk/v0/clients/rest/api/metadata_api.py +0 -728
  28. hatchet_sdk/v0/clients/rest/api/rate_limits_api.py +0 -423
  29. hatchet_sdk/v0/clients/rest/api/slack_api.py +0 -577
  30. hatchet_sdk/v0/clients/rest/api/sns_api.py +0 -872
  31. hatchet_sdk/v0/clients/rest/api/step_run_api.py +0 -2202
  32. hatchet_sdk/v0/clients/rest/api/tenant_api.py +0 -4430
  33. hatchet_sdk/v0/clients/rest/api/user_api.py +0 -2888
  34. hatchet_sdk/v0/clients/rest/api/worker_api.py +0 -858
  35. hatchet_sdk/v0/clients/rest/api/workflow_api.py +0 -6312
  36. hatchet_sdk/v0/clients/rest/api/workflow_run_api.py +0 -1932
  37. hatchet_sdk/v0/clients/rest/api/workflow_runs_api.py +0 -610
  38. hatchet_sdk/v0/clients/rest/api_client.py +0 -759
  39. hatchet_sdk/v0/clients/rest/api_response.py +0 -22
  40. hatchet_sdk/v0/clients/rest/configuration.py +0 -611
  41. hatchet_sdk/v0/clients/rest/exceptions.py +0 -200
  42. hatchet_sdk/v0/clients/rest/models/__init__.py +0 -274
  43. hatchet_sdk/v0/clients/rest/models/accept_invite_request.py +0 -83
  44. hatchet_sdk/v0/clients/rest/models/api_error.py +0 -102
  45. hatchet_sdk/v0/clients/rest/models/api_errors.py +0 -100
  46. hatchet_sdk/v0/clients/rest/models/api_meta.py +0 -144
  47. hatchet_sdk/v0/clients/rest/models/api_meta_auth.py +0 -85
  48. hatchet_sdk/v0/clients/rest/models/api_meta_integration.py +0 -88
  49. hatchet_sdk/v0/clients/rest/models/api_meta_posthog.py +0 -90
  50. hatchet_sdk/v0/clients/rest/models/api_resource_meta.py +0 -98
  51. hatchet_sdk/v0/clients/rest/models/api_token.py +0 -105
  52. hatchet_sdk/v0/clients/rest/models/bulk_create_event_request.py +0 -100
  53. hatchet_sdk/v0/clients/rest/models/bulk_create_event_response.py +0 -110
  54. hatchet_sdk/v0/clients/rest/models/cancel_event_request.py +0 -85
  55. hatchet_sdk/v0/clients/rest/models/cancel_step_run_request.py +0 -83
  56. hatchet_sdk/v0/clients/rest/models/concurrency_limit_strategy.py +0 -39
  57. hatchet_sdk/v0/clients/rest/models/create_api_token_request.py +0 -92
  58. hatchet_sdk/v0/clients/rest/models/create_api_token_response.py +0 -83
  59. hatchet_sdk/v0/clients/rest/models/create_cron_workflow_trigger_request.py +0 -98
  60. hatchet_sdk/v0/clients/rest/models/create_event_request.py +0 -95
  61. hatchet_sdk/v0/clients/rest/models/create_pull_request_from_step_run.py +0 -83
  62. hatchet_sdk/v0/clients/rest/models/create_sns_integration_request.py +0 -85
  63. hatchet_sdk/v0/clients/rest/models/create_tenant_alert_email_group_request.py +0 -83
  64. hatchet_sdk/v0/clients/rest/models/create_tenant_invite_request.py +0 -86
  65. hatchet_sdk/v0/clients/rest/models/create_tenant_request.py +0 -84
  66. hatchet_sdk/v0/clients/rest/models/cron_workflows.py +0 -131
  67. hatchet_sdk/v0/clients/rest/models/cron_workflows_list.py +0 -110
  68. hatchet_sdk/v0/clients/rest/models/cron_workflows_method.py +0 -37
  69. hatchet_sdk/v0/clients/rest/models/cron_workflows_order_by_field.py +0 -37
  70. hatchet_sdk/v0/clients/rest/models/event.py +0 -143
  71. hatchet_sdk/v0/clients/rest/models/event_data.py +0 -83
  72. hatchet_sdk/v0/clients/rest/models/event_key_list.py +0 -98
  73. hatchet_sdk/v0/clients/rest/models/event_list.py +0 -110
  74. hatchet_sdk/v0/clients/rest/models/event_order_by_direction.py +0 -37
  75. hatchet_sdk/v0/clients/rest/models/event_order_by_field.py +0 -36
  76. hatchet_sdk/v0/clients/rest/models/event_update_cancel200_response.py +0 -85
  77. hatchet_sdk/v0/clients/rest/models/event_workflow_run_summary.py +0 -116
  78. hatchet_sdk/v0/clients/rest/models/events.py +0 -110
  79. hatchet_sdk/v0/clients/rest/models/get_step_run_diff_response.py +0 -100
  80. hatchet_sdk/v0/clients/rest/models/github_app_installation.py +0 -107
  81. hatchet_sdk/v0/clients/rest/models/github_branch.py +0 -86
  82. hatchet_sdk/v0/clients/rest/models/github_repo.py +0 -86
  83. hatchet_sdk/v0/clients/rest/models/info_get_version200_response.py +0 -83
  84. hatchet_sdk/v0/clients/rest/models/job.py +0 -132
  85. hatchet_sdk/v0/clients/rest/models/job_run.py +0 -176
  86. hatchet_sdk/v0/clients/rest/models/job_run_status.py +0 -41
  87. hatchet_sdk/v0/clients/rest/models/link_github_repository_request.py +0 -106
  88. hatchet_sdk/v0/clients/rest/models/list_api_tokens_response.py +0 -110
  89. hatchet_sdk/v0/clients/rest/models/list_github_app_installations_response.py +0 -112
  90. hatchet_sdk/v0/clients/rest/models/list_pull_requests_response.py +0 -100
  91. hatchet_sdk/v0/clients/rest/models/list_slack_webhooks.py +0 -110
  92. hatchet_sdk/v0/clients/rest/models/list_sns_integrations.py +0 -110
  93. hatchet_sdk/v0/clients/rest/models/log_line.py +0 -94
  94. hatchet_sdk/v0/clients/rest/models/log_line_level.py +0 -39
  95. hatchet_sdk/v0/clients/rest/models/log_line_list.py +0 -110
  96. hatchet_sdk/v0/clients/rest/models/log_line_order_by_direction.py +0 -37
  97. hatchet_sdk/v0/clients/rest/models/log_line_order_by_field.py +0 -36
  98. hatchet_sdk/v0/clients/rest/models/pagination_response.py +0 -95
  99. hatchet_sdk/v0/clients/rest/models/pull_request.py +0 -112
  100. hatchet_sdk/v0/clients/rest/models/pull_request_state.py +0 -37
  101. hatchet_sdk/v0/clients/rest/models/queue_metrics.py +0 -97
  102. hatchet_sdk/v0/clients/rest/models/rate_limit.py +0 -117
  103. hatchet_sdk/v0/clients/rest/models/rate_limit_list.py +0 -110
  104. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_direction.py +0 -37
  105. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_field.py +0 -38
  106. hatchet_sdk/v0/clients/rest/models/recent_step_runs.py +0 -118
  107. hatchet_sdk/v0/clients/rest/models/reject_invite_request.py +0 -83
  108. hatchet_sdk/v0/clients/rest/models/replay_event_request.py +0 -85
  109. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_request.py +0 -85
  110. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_response.py +0 -100
  111. hatchet_sdk/v0/clients/rest/models/rerun_step_run_request.py +0 -83
  112. hatchet_sdk/v0/clients/rest/models/schedule_workflow_run_request.py +0 -92
  113. hatchet_sdk/v0/clients/rest/models/scheduled_run_status.py +0 -42
  114. hatchet_sdk/v0/clients/rest/models/scheduled_workflows.py +0 -149
  115. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_list.py +0 -110
  116. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_method.py +0 -37
  117. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_order_by_field.py +0 -37
  118. hatchet_sdk/v0/clients/rest/models/semaphore_slots.py +0 -113
  119. hatchet_sdk/v0/clients/rest/models/slack_webhook.py +0 -127
  120. hatchet_sdk/v0/clients/rest/models/sns_integration.py +0 -114
  121. hatchet_sdk/v0/clients/rest/models/step.py +0 -123
  122. hatchet_sdk/v0/clients/rest/models/step_run.py +0 -202
  123. hatchet_sdk/v0/clients/rest/models/step_run_archive.py +0 -142
  124. hatchet_sdk/v0/clients/rest/models/step_run_archive_list.py +0 -110
  125. hatchet_sdk/v0/clients/rest/models/step_run_diff.py +0 -91
  126. hatchet_sdk/v0/clients/rest/models/step_run_event.py +0 -122
  127. hatchet_sdk/v0/clients/rest/models/step_run_event_list.py +0 -110
  128. hatchet_sdk/v0/clients/rest/models/step_run_event_reason.py +0 -52
  129. hatchet_sdk/v0/clients/rest/models/step_run_event_severity.py +0 -38
  130. hatchet_sdk/v0/clients/rest/models/step_run_status.py +0 -44
  131. hatchet_sdk/v0/clients/rest/models/tenant.py +0 -118
  132. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group.py +0 -98
  133. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group_list.py +0 -112
  134. hatchet_sdk/v0/clients/rest/models/tenant_alerting_settings.py +0 -143
  135. hatchet_sdk/v0/clients/rest/models/tenant_invite.py +0 -120
  136. hatchet_sdk/v0/clients/rest/models/tenant_invite_list.py +0 -110
  137. hatchet_sdk/v0/clients/rest/models/tenant_list.py +0 -110
  138. hatchet_sdk/v0/clients/rest/models/tenant_member.py +0 -123
  139. hatchet_sdk/v0/clients/rest/models/tenant_member_list.py +0 -110
  140. hatchet_sdk/v0/clients/rest/models/tenant_member_role.py +0 -38
  141. hatchet_sdk/v0/clients/rest/models/tenant_queue_metrics.py +0 -116
  142. hatchet_sdk/v0/clients/rest/models/tenant_resource.py +0 -40
  143. hatchet_sdk/v0/clients/rest/models/tenant_resource_limit.py +0 -135
  144. hatchet_sdk/v0/clients/rest/models/tenant_resource_policy.py +0 -102
  145. hatchet_sdk/v0/clients/rest/models/tenant_step_run_queue_metrics.py +0 -83
  146. hatchet_sdk/v0/clients/rest/models/trigger_workflow_run_request.py +0 -91
  147. hatchet_sdk/v0/clients/rest/models/update_tenant_alert_email_group_request.py +0 -83
  148. hatchet_sdk/v0/clients/rest/models/update_tenant_invite_request.py +0 -85
  149. hatchet_sdk/v0/clients/rest/models/update_tenant_request.py +0 -137
  150. hatchet_sdk/v0/clients/rest/models/update_worker_request.py +0 -87
  151. hatchet_sdk/v0/clients/rest/models/user.py +0 -126
  152. hatchet_sdk/v0/clients/rest/models/user_change_password_request.py +0 -88
  153. hatchet_sdk/v0/clients/rest/models/user_login_request.py +0 -86
  154. hatchet_sdk/v0/clients/rest/models/user_register_request.py +0 -91
  155. hatchet_sdk/v0/clients/rest/models/user_tenant_memberships_list.py +0 -110
  156. hatchet_sdk/v0/clients/rest/models/user_tenant_public.py +0 -86
  157. hatchet_sdk/v0/clients/rest/models/webhook_worker.py +0 -100
  158. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_request.py +0 -94
  159. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_response.py +0 -98
  160. hatchet_sdk/v0/clients/rest/models/webhook_worker_created.py +0 -102
  161. hatchet_sdk/v0/clients/rest/models/webhook_worker_list_response.py +0 -110
  162. hatchet_sdk/v0/clients/rest/models/webhook_worker_request.py +0 -102
  163. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_list_response.py +0 -104
  164. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_method.py +0 -38
  165. hatchet_sdk/v0/clients/rest/models/worker.py +0 -239
  166. hatchet_sdk/v0/clients/rest/models/worker_label.py +0 -102
  167. hatchet_sdk/v0/clients/rest/models/worker_list.py +0 -110
  168. hatchet_sdk/v0/clients/rest/models/worker_runtime_info.py +0 -103
  169. hatchet_sdk/v0/clients/rest/models/worker_runtime_sdks.py +0 -38
  170. hatchet_sdk/v0/clients/rest/models/worker_type.py +0 -38
  171. hatchet_sdk/v0/clients/rest/models/workflow.py +0 -165
  172. hatchet_sdk/v0/clients/rest/models/workflow_concurrency.py +0 -107
  173. hatchet_sdk/v0/clients/rest/models/workflow_deployment_config.py +0 -136
  174. hatchet_sdk/v0/clients/rest/models/workflow_kind.py +0 -38
  175. hatchet_sdk/v0/clients/rest/models/workflow_list.py +0 -120
  176. hatchet_sdk/v0/clients/rest/models/workflow_metrics.py +0 -97
  177. hatchet_sdk/v0/clients/rest/models/workflow_run.py +0 -188
  178. hatchet_sdk/v0/clients/rest/models/workflow_run_cancel200_response.py +0 -85
  179. hatchet_sdk/v0/clients/rest/models/workflow_run_list.py +0 -110
  180. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_direction.py +0 -37
  181. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_field.py +0 -39
  182. hatchet_sdk/v0/clients/rest/models/workflow_run_shape.py +0 -186
  183. hatchet_sdk/v0/clients/rest/models/workflow_run_status.py +0 -42
  184. hatchet_sdk/v0/clients/rest/models/workflow_run_triggered_by.py +0 -112
  185. hatchet_sdk/v0/clients/rest/models/workflow_runs_cancel_request.py +0 -85
  186. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics.py +0 -94
  187. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics_counts.py +0 -104
  188. hatchet_sdk/v0/clients/rest/models/workflow_tag.py +0 -84
  189. hatchet_sdk/v0/clients/rest/models/workflow_trigger_cron_ref.py +0 -86
  190. hatchet_sdk/v0/clients/rest/models/workflow_trigger_event_ref.py +0 -86
  191. hatchet_sdk/v0/clients/rest/models/workflow_triggers.py +0 -141
  192. hatchet_sdk/v0/clients/rest/models/workflow_update_request.py +0 -85
  193. hatchet_sdk/v0/clients/rest/models/workflow_version.py +0 -170
  194. hatchet_sdk/v0/clients/rest/models/workflow_version_concurrency.py +0 -114
  195. hatchet_sdk/v0/clients/rest/models/workflow_version_definition.py +0 -85
  196. hatchet_sdk/v0/clients/rest/models/workflow_version_meta.py +0 -123
  197. hatchet_sdk/v0/clients/rest/models/workflow_workers_count.py +0 -95
  198. hatchet_sdk/v0/clients/rest/rest.py +0 -187
  199. hatchet_sdk/v0/clients/rest/tenacity_utils.py +0 -39
  200. hatchet_sdk/v0/clients/rest_client.py +0 -622
  201. hatchet_sdk/v0/clients/run_event_listener.py +0 -260
  202. hatchet_sdk/v0/clients/workflow_listener.py +0 -277
  203. hatchet_sdk/v0/connection.py +0 -63
  204. hatchet_sdk/v0/context/__init__.py +0 -1
  205. hatchet_sdk/v0/context/context.py +0 -446
  206. hatchet_sdk/v0/context/worker_context.py +0 -28
  207. hatchet_sdk/v0/features/cron.py +0 -286
  208. hatchet_sdk/v0/features/scheduled.py +0 -248
  209. hatchet_sdk/v0/hatchet.py +0 -310
  210. hatchet_sdk/v0/labels.py +0 -10
  211. hatchet_sdk/v0/loader.py +0 -244
  212. hatchet_sdk/v0/metadata.py +0 -2
  213. hatchet_sdk/v0/opentelemetry/instrumentor.py +0 -393
  214. hatchet_sdk/v0/rate_limit.py +0 -126
  215. hatchet_sdk/v0/semver.py +0 -30
  216. hatchet_sdk/v0/token.py +0 -27
  217. hatchet_sdk/v0/utils/aio_utils.py +0 -137
  218. hatchet_sdk/v0/utils/backoff.py +0 -9
  219. hatchet_sdk/v0/utils/types.py +0 -8
  220. hatchet_sdk/v0/utils/typing.py +0 -12
  221. hatchet_sdk/v0/v2/callable.py +0 -202
  222. hatchet_sdk/v0/v2/concurrency.py +0 -47
  223. hatchet_sdk/v0/v2/hatchet.py +0 -224
  224. hatchet_sdk/v0/worker/__init__.py +0 -1
  225. hatchet_sdk/v0/worker/action_listener_process.py +0 -294
  226. hatchet_sdk/v0/worker/runner/run_loop_manager.py +0 -112
  227. hatchet_sdk/v0/worker/runner/runner.py +0 -460
  228. hatchet_sdk/v0/worker/runner/utils/capture_logs.py +0 -81
  229. hatchet_sdk/v0/worker/runner/utils/error_with_traceback.py +0 -6
  230. hatchet_sdk/v0/worker/worker.py +0 -391
  231. hatchet_sdk/v0/workflow.py +0 -261
  232. hatchet_sdk/v0/workflow_run.py +0 -59
  233. {hatchet_sdk-1.18.1.dist-info → hatchet_sdk-1.20.0.dist-info}/WHEEL +0 -0
  234. {hatchet_sdk-1.18.1.dist-info → hatchet_sdk-1.20.0.dist-info}/entry_points.txt +0 -0
@@ -1,294 +0,0 @@
1
- import asyncio
2
- import logging
3
- import signal
4
- import time
5
- from dataclasses import dataclass, field
6
- from multiprocessing import Queue
7
- from typing import Any, List, Mapping, Optional
8
-
9
- import grpc
10
-
11
- from hatchet_sdk.contracts.dispatcher_pb2 import (
12
- GROUP_KEY_EVENT_TYPE_STARTED,
13
- STEP_EVENT_TYPE_STARTED,
14
- ActionType,
15
- )
16
- from hatchet_sdk.logger import logger
17
- from hatchet_sdk.v0.client import Client, new_client_raw
18
- from hatchet_sdk.v0.clients.dispatcher.action_listener import Action
19
- from hatchet_sdk.v0.clients.dispatcher.dispatcher import (
20
- ActionListener,
21
- GetActionListenerRequest,
22
- new_dispatcher,
23
- )
24
- from hatchet_sdk.v0.clients.rest.models.update_worker_request import UpdateWorkerRequest
25
- from hatchet_sdk.v0.loader import ClientConfig
26
- from hatchet_sdk.v0.utils.backoff import exp_backoff_sleep
27
-
28
- ACTION_EVENT_RETRY_COUNT = 5
29
-
30
-
31
- @dataclass
32
- class ActionEvent:
33
- action: Action
34
- type: Any # TODO type
35
- payload: Optional[str] = None
36
-
37
-
38
- STOP_LOOP = "STOP_LOOP" # Sentinel object to stop the loop
39
-
40
- # TODO link to a block post
41
- BLOCKED_THREAD_WARNING = (
42
- "THE TIME TO START THE STEP RUN IS TOO LONG, THE MAIN THREAD MAY BE BLOCKED"
43
- )
44
-
45
-
46
- def noop_handler():
47
- pass
48
-
49
-
50
- @dataclass
51
- class WorkerActionListenerProcess:
52
- name: str
53
- actions: List[str]
54
- max_runs: int
55
- config: ClientConfig
56
- action_queue: Queue
57
- event_queue: Queue
58
- handle_kill: bool = True
59
- debug: bool = False
60
- labels: dict = field(default_factory=dict)
61
-
62
- listener: ActionListener = field(init=False, default=None)
63
-
64
- killing: bool = field(init=False, default=False)
65
-
66
- action_loop_task: asyncio.Task = field(init=False, default=None)
67
- event_send_loop_task: asyncio.Task = field(init=False, default=None)
68
-
69
- running_step_runs: Mapping[str, float] = field(init=False, default_factory=dict)
70
-
71
- def __post_init__(self):
72
- if self.debug:
73
- logger.setLevel(logging.DEBUG)
74
-
75
- self.client = new_client_raw(self.config, self.debug)
76
-
77
- loop = asyncio.get_event_loop()
78
- loop.add_signal_handler(
79
- signal.SIGINT, lambda: asyncio.create_task(self.pause_task_assignment())
80
- )
81
- loop.add_signal_handler(
82
- signal.SIGTERM, lambda: asyncio.create_task(self.pause_task_assignment())
83
- )
84
- loop.add_signal_handler(
85
- signal.SIGQUIT, lambda: asyncio.create_task(self.exit_gracefully())
86
- )
87
-
88
- async def start(self, retry_attempt=0):
89
- if retry_attempt > 5:
90
- logger.error("could not start action listener")
91
- return
92
-
93
- logger.debug(f"starting action listener: {self.name}")
94
-
95
- try:
96
- self.dispatcher_client = new_dispatcher(self.config)
97
-
98
- self.listener = await self.dispatcher_client.get_action_listener(
99
- GetActionListenerRequest(
100
- worker_name=self.name,
101
- services=["default"],
102
- actions=self.actions,
103
- max_runs=self.max_runs,
104
- _labels=self.labels,
105
- )
106
- )
107
-
108
- logger.debug(f"acquired action listener: {self.listener.worker_id}")
109
- except grpc.RpcError as rpc_error:
110
- logger.error(f"could not start action listener: {rpc_error}")
111
- return
112
-
113
- # Start both loops as background tasks
114
- self.action_loop_task = asyncio.create_task(self.start_action_loop())
115
- self.event_send_loop_task = asyncio.create_task(self.start_event_send_loop())
116
- self.blocked_main_loop = asyncio.create_task(self.start_blocked_main_loop())
117
-
118
- # TODO move event methods to separate class
119
- async def _get_event(self):
120
- loop = asyncio.get_running_loop()
121
- return await loop.run_in_executor(None, self.event_queue.get)
122
-
123
- async def start_event_send_loop(self):
124
- while True:
125
- event: ActionEvent = await self._get_event()
126
- if event == STOP_LOOP:
127
- logger.debug("stopping event send loop...")
128
- break
129
-
130
- logger.debug(f"tx: event: {event.action.action_id}/{event.type}")
131
- asyncio.create_task(self.send_event(event))
132
-
133
- async def start_blocked_main_loop(self):
134
- threshold = 1
135
- while not self.killing:
136
- count = 0
137
- for step_run_id, start_time in self.running_step_runs.items():
138
- diff = self.now() - start_time
139
- if diff > threshold:
140
- count += 1
141
-
142
- if count > 0:
143
- logger.warning(f"{BLOCKED_THREAD_WARNING}: Waiting Steps {count}")
144
- await asyncio.sleep(1)
145
-
146
- async def send_event(self, event: ActionEvent, retry_attempt: int = 1):
147
- try:
148
- match event.action.action_type:
149
- # FIXME: all events sent from an execution of a function are of type ActionType.START_STEP_RUN since
150
- # the action is re-used. We should change this.
151
- case ActionType.START_STEP_RUN:
152
- # TODO right now we're sending two start_step_run events
153
- # one on the action loop and one on the event loop
154
- # ideally we change the first to an ack to set the time
155
- if event.type == STEP_EVENT_TYPE_STARTED:
156
- if event.action.step_run_id in self.running_step_runs:
157
- diff = (
158
- self.now()
159
- - self.running_step_runs[event.action.step_run_id]
160
- )
161
- if diff > 0.1:
162
- logger.warning(
163
- f"{BLOCKED_THREAD_WARNING}: time to start: {diff}s"
164
- )
165
- else:
166
- logger.debug(f"start time: {diff}")
167
- del self.running_step_runs[event.action.step_run_id]
168
- else:
169
- self.running_step_runs[event.action.step_run_id] = (
170
- self.now()
171
- )
172
-
173
- asyncio.create_task(
174
- self.dispatcher_client.send_step_action_event(
175
- event.action, event.type, event.payload
176
- )
177
- )
178
- case ActionType.CANCEL_STEP_RUN:
179
- logger.debug("unimplemented event send")
180
- case ActionType.START_GET_GROUP_KEY:
181
- asyncio.create_task(
182
- self.dispatcher_client.send_group_key_action_event(
183
- event.action, event.type, event.payload
184
- )
185
- )
186
- case _:
187
- logger.error("unknown action type for event send")
188
- except Exception as e:
189
- logger.error(
190
- f"could not send action event ({retry_attempt}/{ACTION_EVENT_RETRY_COUNT}): {e}"
191
- )
192
- if retry_attempt <= ACTION_EVENT_RETRY_COUNT:
193
- await exp_backoff_sleep(retry_attempt, 1)
194
- await self.send_event(event, retry_attempt + 1)
195
-
196
- def now(self):
197
- return time.time()
198
-
199
- async def start_action_loop(self):
200
- try:
201
- async for action in self.listener:
202
- if action is None:
203
- break
204
-
205
- # Process the action here
206
- match action.action_type:
207
- case ActionType.START_STEP_RUN:
208
- self.event_queue.put(
209
- ActionEvent(
210
- action=action,
211
- type=STEP_EVENT_TYPE_STARTED, # TODO ack type
212
- )
213
- )
214
- logger.info(
215
- f"rx: start step run: {action.step_run_id}/{action.action_id}"
216
- )
217
-
218
- # TODO handle this case better...
219
- if action.step_run_id in self.running_step_runs:
220
- logger.warning(
221
- f"step run already running: {action.step_run_id}"
222
- )
223
-
224
- case ActionType.CANCEL_STEP_RUN:
225
- logger.info(f"rx: cancel step run: {action.step_run_id}")
226
- case ActionType.START_GET_GROUP_KEY:
227
- self.event_queue.put(
228
- ActionEvent(
229
- action=action,
230
- type=GROUP_KEY_EVENT_TYPE_STARTED, # TODO ack type
231
- )
232
- )
233
- logger.info(
234
- f"rx: start group key: {action.get_group_key_run_id}"
235
- )
236
- case _:
237
- logger.error(
238
- f"rx: unknown action type ({action.action_type}): {action.action_type}"
239
- )
240
- try:
241
- self.action_queue.put(action)
242
- except Exception as e:
243
- logger.error(f"error putting action: {e}")
244
-
245
- except Exception as e:
246
- logger.error(f"error in action loop: {e}")
247
- finally:
248
- logger.info("action loop closed")
249
- if not self.killing:
250
- await self.exit_gracefully(skip_unregister=True)
251
-
252
- async def cleanup(self):
253
- self.killing = True
254
-
255
- if self.listener is not None:
256
- self.listener.cleanup()
257
-
258
- self.event_queue.put(STOP_LOOP)
259
-
260
- async def pause_task_assignment(self) -> None:
261
- await self.client.rest.aio.worker_api.worker_update(
262
- worker=self.listener.worker_id,
263
- update_worker_request=UpdateWorkerRequest(isPaused=True),
264
- )
265
-
266
- async def exit_gracefully(self, skip_unregister=False):
267
- await self.pause_task_assignment()
268
-
269
- if self.killing:
270
- return
271
-
272
- logger.debug("closing action listener...")
273
-
274
- await self.cleanup()
275
-
276
- while not self.event_queue.empty():
277
- pass
278
-
279
- logger.info("action listener closed")
280
-
281
- def exit_forcefully(self):
282
- asyncio.run(self.cleanup())
283
- logger.debug("forcefully closing listener...")
284
-
285
-
286
- def worker_action_listener_process(*args, **kwargs):
287
- async def run():
288
- process = WorkerActionListenerProcess(*args, **kwargs)
289
- await process.start()
290
- # Keep the process running
291
- while not process.killing:
292
- await asyncio.sleep(0.1)
293
-
294
- asyncio.run(run())
@@ -1,112 +0,0 @@
1
- import asyncio
2
- import logging
3
- from dataclasses import dataclass, field
4
- from multiprocessing import Queue
5
- from typing import Callable, TypeVar
6
-
7
- from hatchet_sdk.logger import logger
8
- from hatchet_sdk.v0 import Context
9
- from hatchet_sdk.v0.client import Client, new_client_raw
10
- from hatchet_sdk.v0.clients.dispatcher.action_listener import Action
11
- from hatchet_sdk.v0.loader import ClientConfig
12
- from hatchet_sdk.v0.utils.types import WorkflowValidator
13
- from hatchet_sdk.v0.worker.runner.runner import Runner
14
- from hatchet_sdk.v0.worker.runner.utils.capture_logs import capture_logs
15
-
16
- STOP_LOOP = "STOP_LOOP"
17
-
18
- T = TypeVar("T")
19
-
20
-
21
- @dataclass
22
- class WorkerActionRunLoopManager:
23
- name: str
24
- action_registry: dict[str, Callable[[Context], T]]
25
- validator_registry: dict[str, WorkflowValidator]
26
- max_runs: int | None
27
- config: ClientConfig
28
- action_queue: Queue
29
- event_queue: Queue
30
- loop: asyncio.AbstractEventLoop
31
- handle_kill: bool = True
32
- debug: bool = False
33
- labels: dict[str, str | int] = field(default_factory=dict)
34
-
35
- client: Client = field(init=False, default=None)
36
-
37
- killing: bool = field(init=False, default=False)
38
- runner: Runner = field(init=False, default=None)
39
-
40
- def __post_init__(self):
41
- if self.debug:
42
- logger.setLevel(logging.DEBUG)
43
- self.client = new_client_raw(self.config, self.debug)
44
- self.start()
45
-
46
- def start(self, retry_count=1):
47
- k = self.loop.create_task(self.async_start(retry_count))
48
-
49
- async def async_start(self, retry_count=1):
50
- await capture_logs(
51
- self.client.logInterceptor,
52
- self.client.event,
53
- self._async_start,
54
- )(retry_count=retry_count)
55
-
56
- async def _async_start(self, retry_count: int = 1) -> None:
57
- logger.info("starting runner...")
58
- self.loop = asyncio.get_running_loop()
59
- # needed for graceful termination
60
- k = self.loop.create_task(self._start_action_loop())
61
- await k
62
-
63
- def cleanup(self) -> None:
64
- self.killing = True
65
-
66
- self.action_queue.put(STOP_LOOP)
67
-
68
- async def wait_for_tasks(self) -> None:
69
- if self.runner:
70
- await self.runner.wait_for_tasks()
71
-
72
- async def _start_action_loop(self) -> None:
73
- self.runner = Runner(
74
- self.name,
75
- self.event_queue,
76
- self.max_runs,
77
- self.handle_kill,
78
- self.action_registry,
79
- self.validator_registry,
80
- self.config,
81
- self.labels,
82
- )
83
-
84
- logger.debug(f"'{self.name}' waiting for {list(self.action_registry.keys())}")
85
- while not self.killing:
86
- action: Action = await self._get_action()
87
- if action == STOP_LOOP:
88
- logger.debug("stopping action runner loop...")
89
- break
90
-
91
- self.runner.run(action)
92
- logger.debug("action runner loop stopped")
93
-
94
- async def _get_action(self):
95
- return await self.loop.run_in_executor(None, self.action_queue.get)
96
-
97
- async def exit_gracefully(self) -> None:
98
- if self.killing:
99
- return
100
-
101
- logger.info("gracefully exiting runner...")
102
-
103
- self.cleanup()
104
-
105
- # Wait for 1 second to allow last calls to flush. These are calls which have been
106
- # added to the event loop as callbacks to tasks, so we're not aware of them in the
107
- # task list.
108
- await asyncio.sleep(1)
109
-
110
- def exit_forcefully(self) -> None:
111
- logger.info("forcefully exiting runner...")
112
- self.cleanup()