hatchet-sdk 0.47.1__py3-none-any.whl → 1.0.0a1__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 (329) hide show
  1. hatchet_sdk/__init__.py +45 -25
  2. hatchet_sdk/client.py +19 -94
  3. hatchet_sdk/clients/admin.py +309 -389
  4. hatchet_sdk/clients/dispatcher/action_listener.py +131 -109
  5. hatchet_sdk/clients/dispatcher/dispatcher.py +39 -37
  6. hatchet_sdk/clients/durable_event_listener.py +327 -0
  7. hatchet_sdk/clients/event_ts.py +23 -10
  8. hatchet_sdk/clients/events.py +96 -99
  9. hatchet_sdk/clients/rest/__init__.py +35 -0
  10. hatchet_sdk/clients/rest/api/__init__.py +2 -0
  11. hatchet_sdk/clients/rest/api/log_api.py +258 -0
  12. hatchet_sdk/clients/rest/api/task_api.py +2200 -0
  13. hatchet_sdk/clients/rest/api/workflow_runs_api.py +1274 -116
  14. hatchet_sdk/clients/rest/api_client.py +1 -1
  15. hatchet_sdk/clients/rest/configuration.py +8 -1
  16. hatchet_sdk/clients/rest/exceptions.py +21 -0
  17. hatchet_sdk/clients/rest/models/__init__.py +33 -0
  18. hatchet_sdk/clients/rest/models/tenant.py +4 -0
  19. hatchet_sdk/clients/rest/models/tenant_version.py +37 -0
  20. hatchet_sdk/clients/rest/models/update_tenant_request.py +7 -0
  21. hatchet_sdk/clients/rest/models/v1_cancel_task_request.py +104 -0
  22. hatchet_sdk/clients/rest/models/v1_dag_children.py +102 -0
  23. hatchet_sdk/clients/rest/models/v1_log_line.py +94 -0
  24. hatchet_sdk/clients/rest/models/v1_log_line_level.py +39 -0
  25. hatchet_sdk/clients/rest/models/v1_log_line_list.py +110 -0
  26. hatchet_sdk/clients/rest/models/v1_replay_task_request.py +104 -0
  27. hatchet_sdk/clients/rest/models/v1_task.py +174 -0
  28. hatchet_sdk/clients/rest/models/v1_task_event.py +118 -0
  29. hatchet_sdk/clients/rest/models/v1_task_event_list.py +110 -0
  30. hatchet_sdk/clients/rest/models/v1_task_event_type.py +55 -0
  31. hatchet_sdk/clients/rest/models/v1_task_filter.py +106 -0
  32. hatchet_sdk/clients/rest/models/v1_task_point_metric.py +92 -0
  33. hatchet_sdk/clients/rest/models/v1_task_point_metrics.py +100 -0
  34. hatchet_sdk/clients/rest/models/v1_task_run_metric.py +88 -0
  35. hatchet_sdk/clients/rest/models/v1_task_run_status.py +40 -0
  36. hatchet_sdk/clients/rest/models/v1_task_status.py +40 -0
  37. hatchet_sdk/clients/rest/models/v1_task_summary.py +228 -0
  38. hatchet_sdk/clients/rest/models/v1_task_summary_list.py +110 -0
  39. hatchet_sdk/clients/rest/models/v1_trigger_workflow_run_request.py +95 -0
  40. hatchet_sdk/clients/rest/models/v1_workflow_run.py +171 -0
  41. hatchet_sdk/clients/rest/models/v1_workflow_run_details.py +145 -0
  42. hatchet_sdk/clients/rest/models/v1_workflow_run_display_name.py +98 -0
  43. hatchet_sdk/clients/rest/models/v1_workflow_run_display_name_list.py +114 -0
  44. hatchet_sdk/clients/rest/models/v1_workflow_type.py +37 -0
  45. hatchet_sdk/clients/rest/models/workflow_run_shape_item_for_workflow_run_details.py +104 -0
  46. hatchet_sdk/clients/rest/rest.py +37 -26
  47. hatchet_sdk/clients/rest/tenacity_utils.py +1 -1
  48. hatchet_sdk/clients/rest_client.py +153 -116
  49. hatchet_sdk/clients/run_event_listener.py +65 -60
  50. hatchet_sdk/clients/workflow_listener.py +75 -66
  51. hatchet_sdk/config.py +117 -0
  52. hatchet_sdk/connection.py +27 -13
  53. hatchet_sdk/context/__init__.py +0 -1
  54. hatchet_sdk/context/context.py +118 -280
  55. hatchet_sdk/contracts/dispatcher_pb2_grpc.py +1 -1
  56. hatchet_sdk/contracts/events_pb2.py +2 -2
  57. hatchet_sdk/contracts/events_pb2_grpc.py +1 -1
  58. hatchet_sdk/contracts/v1/dispatcher_pb2.py +36 -0
  59. hatchet_sdk/contracts/v1/dispatcher_pb2.pyi +38 -0
  60. hatchet_sdk/contracts/v1/dispatcher_pb2_grpc.py +145 -0
  61. hatchet_sdk/contracts/v1/shared/condition_pb2.py +39 -0
  62. hatchet_sdk/contracts/v1/shared/condition_pb2.pyi +72 -0
  63. hatchet_sdk/contracts/v1/shared/condition_pb2_grpc.py +29 -0
  64. hatchet_sdk/contracts/v1/workflows_pb2.py +67 -0
  65. hatchet_sdk/contracts/v1/workflows_pb2.pyi +228 -0
  66. hatchet_sdk/contracts/v1/workflows_pb2_grpc.py +234 -0
  67. hatchet_sdk/contracts/workflows_pb2_grpc.py +1 -1
  68. hatchet_sdk/features/cron.py +43 -57
  69. hatchet_sdk/features/scheduled.py +60 -74
  70. hatchet_sdk/hatchet.py +491 -218
  71. hatchet_sdk/labels.py +4 -6
  72. hatchet_sdk/metadata.py +1 -1
  73. hatchet_sdk/opentelemetry/instrumentor.py +17 -18
  74. hatchet_sdk/rate_limit.py +40 -55
  75. hatchet_sdk/runnables/contextvars.py +12 -0
  76. hatchet_sdk/runnables/standalone.py +194 -0
  77. hatchet_sdk/runnables/task.py +144 -0
  78. hatchet_sdk/runnables/types.py +138 -0
  79. hatchet_sdk/runnables/workflow.py +764 -0
  80. hatchet_sdk/token.py +13 -9
  81. hatchet_sdk/utils/aio_utils.py +0 -119
  82. hatchet_sdk/utils/proto_enums.py +47 -0
  83. hatchet_sdk/utils/timedelta_to_expression.py +23 -0
  84. hatchet_sdk/utils/typing.py +10 -2
  85. hatchet_sdk/v0/__init__.py +251 -0
  86. hatchet_sdk/v0/client.py +119 -0
  87. hatchet_sdk/v0/clients/admin.py +541 -0
  88. hatchet_sdk/v0/clients/dispatcher/action_listener.py +422 -0
  89. hatchet_sdk/v0/clients/dispatcher/dispatcher.py +204 -0
  90. hatchet_sdk/v0/clients/event_ts.py +28 -0
  91. hatchet_sdk/v0/clients/events.py +182 -0
  92. hatchet_sdk/v0/clients/rest/__init__.py +307 -0
  93. hatchet_sdk/v0/clients/rest/api/__init__.py +19 -0
  94. hatchet_sdk/v0/clients/rest/api/api_token_api.py +858 -0
  95. hatchet_sdk/v0/clients/rest/api/default_api.py +2259 -0
  96. hatchet_sdk/v0/clients/rest/api/event_api.py +2548 -0
  97. hatchet_sdk/v0/clients/rest/api/github_api.py +331 -0
  98. hatchet_sdk/v0/clients/rest/api/healthcheck_api.py +483 -0
  99. hatchet_sdk/v0/clients/rest/api/log_api.py +449 -0
  100. hatchet_sdk/v0/clients/rest/api/metadata_api.py +728 -0
  101. hatchet_sdk/v0/clients/rest/api/rate_limits_api.py +423 -0
  102. hatchet_sdk/v0/clients/rest/api/slack_api.py +577 -0
  103. hatchet_sdk/v0/clients/rest/api/sns_api.py +872 -0
  104. hatchet_sdk/v0/clients/rest/api/step_run_api.py +2202 -0
  105. hatchet_sdk/v0/clients/rest/api/tenant_api.py +4430 -0
  106. hatchet_sdk/v0/clients/rest/api/user_api.py +2888 -0
  107. hatchet_sdk/v0/clients/rest/api/worker_api.py +858 -0
  108. hatchet_sdk/v0/clients/rest/api/workflow_api.py +6312 -0
  109. hatchet_sdk/v0/clients/rest/api/workflow_run_api.py +1932 -0
  110. hatchet_sdk/v0/clients/rest/api/workflow_runs_api.py +610 -0
  111. hatchet_sdk/v0/clients/rest/api_client.py +759 -0
  112. hatchet_sdk/v0/clients/rest/api_response.py +22 -0
  113. hatchet_sdk/v0/clients/rest/configuration.py +611 -0
  114. hatchet_sdk/v0/clients/rest/exceptions.py +200 -0
  115. hatchet_sdk/v0/clients/rest/models/__init__.py +274 -0
  116. hatchet_sdk/v0/clients/rest/models/accept_invite_request.py +83 -0
  117. hatchet_sdk/v0/clients/rest/models/api_error.py +102 -0
  118. hatchet_sdk/v0/clients/rest/models/api_errors.py +100 -0
  119. hatchet_sdk/v0/clients/rest/models/api_meta.py +144 -0
  120. hatchet_sdk/v0/clients/rest/models/api_meta_auth.py +85 -0
  121. hatchet_sdk/v0/clients/rest/models/api_meta_integration.py +88 -0
  122. hatchet_sdk/v0/clients/rest/models/api_meta_posthog.py +90 -0
  123. hatchet_sdk/v0/clients/rest/models/api_resource_meta.py +98 -0
  124. hatchet_sdk/v0/clients/rest/models/api_token.py +105 -0
  125. hatchet_sdk/v0/clients/rest/models/bulk_create_event_request.py +100 -0
  126. hatchet_sdk/v0/clients/rest/models/bulk_create_event_response.py +110 -0
  127. hatchet_sdk/v0/clients/rest/models/cancel_event_request.py +85 -0
  128. hatchet_sdk/v0/clients/rest/models/cancel_step_run_request.py +83 -0
  129. hatchet_sdk/v0/clients/rest/models/concurrency_limit_strategy.py +39 -0
  130. hatchet_sdk/v0/clients/rest/models/create_api_token_request.py +92 -0
  131. hatchet_sdk/v0/clients/rest/models/create_api_token_response.py +83 -0
  132. hatchet_sdk/v0/clients/rest/models/create_cron_workflow_trigger_request.py +98 -0
  133. hatchet_sdk/v0/clients/rest/models/create_event_request.py +95 -0
  134. hatchet_sdk/v0/clients/rest/models/create_pull_request_from_step_run.py +83 -0
  135. hatchet_sdk/v0/clients/rest/models/create_sns_integration_request.py +85 -0
  136. hatchet_sdk/v0/clients/rest/models/create_tenant_alert_email_group_request.py +83 -0
  137. hatchet_sdk/v0/clients/rest/models/create_tenant_invite_request.py +86 -0
  138. hatchet_sdk/v0/clients/rest/models/create_tenant_request.py +84 -0
  139. hatchet_sdk/v0/clients/rest/models/cron_workflows.py +131 -0
  140. hatchet_sdk/v0/clients/rest/models/cron_workflows_list.py +110 -0
  141. hatchet_sdk/v0/clients/rest/models/cron_workflows_method.py +37 -0
  142. hatchet_sdk/v0/clients/rest/models/cron_workflows_order_by_field.py +37 -0
  143. hatchet_sdk/v0/clients/rest/models/event.py +143 -0
  144. hatchet_sdk/v0/clients/rest/models/event_data.py +83 -0
  145. hatchet_sdk/v0/clients/rest/models/event_key_list.py +98 -0
  146. hatchet_sdk/v0/clients/rest/models/event_list.py +110 -0
  147. hatchet_sdk/v0/clients/rest/models/event_order_by_direction.py +37 -0
  148. hatchet_sdk/v0/clients/rest/models/event_order_by_field.py +36 -0
  149. hatchet_sdk/v0/clients/rest/models/event_update_cancel200_response.py +85 -0
  150. hatchet_sdk/v0/clients/rest/models/event_workflow_run_summary.py +116 -0
  151. hatchet_sdk/v0/clients/rest/models/events.py +110 -0
  152. hatchet_sdk/v0/clients/rest/models/get_step_run_diff_response.py +100 -0
  153. hatchet_sdk/v0/clients/rest/models/github_app_installation.py +107 -0
  154. hatchet_sdk/v0/clients/rest/models/github_branch.py +86 -0
  155. hatchet_sdk/v0/clients/rest/models/github_repo.py +86 -0
  156. hatchet_sdk/v0/clients/rest/models/info_get_version200_response.py +83 -0
  157. hatchet_sdk/v0/clients/rest/models/job.py +132 -0
  158. hatchet_sdk/v0/clients/rest/models/job_run.py +176 -0
  159. hatchet_sdk/v0/clients/rest/models/job_run_status.py +41 -0
  160. hatchet_sdk/v0/clients/rest/models/link_github_repository_request.py +106 -0
  161. hatchet_sdk/v0/clients/rest/models/list_api_tokens_response.py +110 -0
  162. hatchet_sdk/v0/clients/rest/models/list_github_app_installations_response.py +112 -0
  163. hatchet_sdk/v0/clients/rest/models/list_pull_requests_response.py +100 -0
  164. hatchet_sdk/v0/clients/rest/models/list_slack_webhooks.py +110 -0
  165. hatchet_sdk/v0/clients/rest/models/list_sns_integrations.py +110 -0
  166. hatchet_sdk/v0/clients/rest/models/log_line.py +94 -0
  167. hatchet_sdk/v0/clients/rest/models/log_line_level.py +39 -0
  168. hatchet_sdk/v0/clients/rest/models/log_line_list.py +110 -0
  169. hatchet_sdk/v0/clients/rest/models/log_line_order_by_direction.py +37 -0
  170. hatchet_sdk/v0/clients/rest/models/log_line_order_by_field.py +36 -0
  171. hatchet_sdk/v0/clients/rest/models/pagination_response.py +95 -0
  172. hatchet_sdk/v0/clients/rest/models/pull_request.py +112 -0
  173. hatchet_sdk/v0/clients/rest/models/pull_request_state.py +37 -0
  174. hatchet_sdk/v0/clients/rest/models/queue_metrics.py +97 -0
  175. hatchet_sdk/v0/clients/rest/models/rate_limit.py +117 -0
  176. hatchet_sdk/v0/clients/rest/models/rate_limit_list.py +110 -0
  177. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_direction.py +37 -0
  178. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_field.py +38 -0
  179. hatchet_sdk/v0/clients/rest/models/recent_step_runs.py +118 -0
  180. hatchet_sdk/v0/clients/rest/models/reject_invite_request.py +83 -0
  181. hatchet_sdk/v0/clients/rest/models/replay_event_request.py +85 -0
  182. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_request.py +85 -0
  183. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_response.py +100 -0
  184. hatchet_sdk/v0/clients/rest/models/rerun_step_run_request.py +83 -0
  185. hatchet_sdk/v0/clients/rest/models/schedule_workflow_run_request.py +92 -0
  186. hatchet_sdk/v0/clients/rest/models/scheduled_run_status.py +42 -0
  187. hatchet_sdk/v0/clients/rest/models/scheduled_workflows.py +149 -0
  188. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_list.py +110 -0
  189. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_method.py +37 -0
  190. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
  191. hatchet_sdk/v0/clients/rest/models/semaphore_slots.py +113 -0
  192. hatchet_sdk/v0/clients/rest/models/slack_webhook.py +127 -0
  193. hatchet_sdk/v0/clients/rest/models/sns_integration.py +114 -0
  194. hatchet_sdk/v0/clients/rest/models/step.py +123 -0
  195. hatchet_sdk/v0/clients/rest/models/step_run.py +202 -0
  196. hatchet_sdk/v0/clients/rest/models/step_run_archive.py +142 -0
  197. hatchet_sdk/v0/clients/rest/models/step_run_archive_list.py +110 -0
  198. hatchet_sdk/v0/clients/rest/models/step_run_diff.py +91 -0
  199. hatchet_sdk/v0/clients/rest/models/step_run_event.py +122 -0
  200. hatchet_sdk/v0/clients/rest/models/step_run_event_list.py +110 -0
  201. hatchet_sdk/v0/clients/rest/models/step_run_event_reason.py +52 -0
  202. hatchet_sdk/v0/clients/rest/models/step_run_event_severity.py +38 -0
  203. hatchet_sdk/v0/clients/rest/models/step_run_status.py +44 -0
  204. hatchet_sdk/v0/clients/rest/models/tenant.py +118 -0
  205. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group.py +98 -0
  206. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group_list.py +112 -0
  207. hatchet_sdk/v0/clients/rest/models/tenant_alerting_settings.py +143 -0
  208. hatchet_sdk/v0/clients/rest/models/tenant_invite.py +120 -0
  209. hatchet_sdk/v0/clients/rest/models/tenant_invite_list.py +110 -0
  210. hatchet_sdk/v0/clients/rest/models/tenant_list.py +110 -0
  211. hatchet_sdk/v0/clients/rest/models/tenant_member.py +123 -0
  212. hatchet_sdk/v0/clients/rest/models/tenant_member_list.py +110 -0
  213. hatchet_sdk/v0/clients/rest/models/tenant_member_role.py +38 -0
  214. hatchet_sdk/v0/clients/rest/models/tenant_queue_metrics.py +116 -0
  215. hatchet_sdk/v0/clients/rest/models/tenant_resource.py +40 -0
  216. hatchet_sdk/v0/clients/rest/models/tenant_resource_limit.py +135 -0
  217. hatchet_sdk/v0/clients/rest/models/tenant_resource_policy.py +102 -0
  218. hatchet_sdk/v0/clients/rest/models/tenant_step_run_queue_metrics.py +83 -0
  219. hatchet_sdk/v0/clients/rest/models/trigger_workflow_run_request.py +91 -0
  220. hatchet_sdk/v0/clients/rest/models/update_tenant_alert_email_group_request.py +83 -0
  221. hatchet_sdk/v0/clients/rest/models/update_tenant_invite_request.py +85 -0
  222. hatchet_sdk/v0/clients/rest/models/update_tenant_request.py +137 -0
  223. hatchet_sdk/v0/clients/rest/models/update_worker_request.py +87 -0
  224. hatchet_sdk/v0/clients/rest/models/user.py +126 -0
  225. hatchet_sdk/v0/clients/rest/models/user_change_password_request.py +88 -0
  226. hatchet_sdk/v0/clients/rest/models/user_login_request.py +86 -0
  227. hatchet_sdk/v0/clients/rest/models/user_register_request.py +91 -0
  228. hatchet_sdk/v0/clients/rest/models/user_tenant_memberships_list.py +110 -0
  229. hatchet_sdk/v0/clients/rest/models/user_tenant_public.py +86 -0
  230. hatchet_sdk/v0/clients/rest/models/webhook_worker.py +100 -0
  231. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_request.py +94 -0
  232. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_response.py +98 -0
  233. hatchet_sdk/v0/clients/rest/models/webhook_worker_created.py +102 -0
  234. hatchet_sdk/v0/clients/rest/models/webhook_worker_list_response.py +110 -0
  235. hatchet_sdk/v0/clients/rest/models/webhook_worker_request.py +102 -0
  236. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_list_response.py +104 -0
  237. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_method.py +38 -0
  238. hatchet_sdk/v0/clients/rest/models/worker.py +239 -0
  239. hatchet_sdk/v0/clients/rest/models/worker_label.py +102 -0
  240. hatchet_sdk/v0/clients/rest/models/worker_list.py +110 -0
  241. hatchet_sdk/v0/clients/rest/models/worker_runtime_info.py +103 -0
  242. hatchet_sdk/v0/clients/rest/models/worker_runtime_sdks.py +38 -0
  243. hatchet_sdk/v0/clients/rest/models/worker_type.py +38 -0
  244. hatchet_sdk/v0/clients/rest/models/workflow.py +165 -0
  245. hatchet_sdk/v0/clients/rest/models/workflow_concurrency.py +107 -0
  246. hatchet_sdk/v0/clients/rest/models/workflow_deployment_config.py +136 -0
  247. hatchet_sdk/v0/clients/rest/models/workflow_kind.py +38 -0
  248. hatchet_sdk/v0/clients/rest/models/workflow_list.py +120 -0
  249. hatchet_sdk/v0/clients/rest/models/workflow_metrics.py +97 -0
  250. hatchet_sdk/v0/clients/rest/models/workflow_run.py +188 -0
  251. hatchet_sdk/v0/clients/rest/models/workflow_run_cancel200_response.py +85 -0
  252. hatchet_sdk/v0/clients/rest/models/workflow_run_list.py +110 -0
  253. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_direction.py +37 -0
  254. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_field.py +39 -0
  255. hatchet_sdk/v0/clients/rest/models/workflow_run_shape.py +186 -0
  256. hatchet_sdk/v0/clients/rest/models/workflow_run_status.py +42 -0
  257. hatchet_sdk/v0/clients/rest/models/workflow_run_triggered_by.py +112 -0
  258. hatchet_sdk/v0/clients/rest/models/workflow_runs_cancel_request.py +85 -0
  259. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics.py +94 -0
  260. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics_counts.py +104 -0
  261. hatchet_sdk/v0/clients/rest/models/workflow_tag.py +84 -0
  262. hatchet_sdk/v0/clients/rest/models/workflow_trigger_cron_ref.py +86 -0
  263. hatchet_sdk/v0/clients/rest/models/workflow_trigger_event_ref.py +86 -0
  264. hatchet_sdk/v0/clients/rest/models/workflow_triggers.py +141 -0
  265. hatchet_sdk/v0/clients/rest/models/workflow_update_request.py +85 -0
  266. hatchet_sdk/v0/clients/rest/models/workflow_version.py +170 -0
  267. hatchet_sdk/v0/clients/rest/models/workflow_version_concurrency.py +114 -0
  268. hatchet_sdk/v0/clients/rest/models/workflow_version_definition.py +85 -0
  269. hatchet_sdk/v0/clients/rest/models/workflow_version_meta.py +123 -0
  270. hatchet_sdk/v0/clients/rest/models/workflow_workers_count.py +95 -0
  271. hatchet_sdk/v0/clients/rest/rest.py +187 -0
  272. hatchet_sdk/v0/clients/rest/tenacity_utils.py +39 -0
  273. hatchet_sdk/v0/clients/rest_client.py +622 -0
  274. hatchet_sdk/v0/clients/run_event_listener.py +260 -0
  275. hatchet_sdk/v0/clients/workflow_listener.py +277 -0
  276. hatchet_sdk/v0/connection.py +63 -0
  277. hatchet_sdk/v0/context/__init__.py +1 -0
  278. hatchet_sdk/v0/context/context.py +446 -0
  279. hatchet_sdk/v0/context/worker_context.py +28 -0
  280. hatchet_sdk/v0/contracts/dispatcher_pb2.py +102 -0
  281. hatchet_sdk/v0/contracts/dispatcher_pb2.pyi +387 -0
  282. hatchet_sdk/v0/contracts/dispatcher_pb2_grpc.py +621 -0
  283. hatchet_sdk/v0/contracts/events_pb2.py +46 -0
  284. hatchet_sdk/v0/contracts/events_pb2.pyi +87 -0
  285. hatchet_sdk/v0/contracts/events_pb2_grpc.py +274 -0
  286. hatchet_sdk/v0/contracts/workflows_pb2.py +80 -0
  287. hatchet_sdk/v0/contracts/workflows_pb2.pyi +312 -0
  288. hatchet_sdk/v0/contracts/workflows_pb2_grpc.py +277 -0
  289. hatchet_sdk/v0/features/cron.py +286 -0
  290. hatchet_sdk/v0/features/scheduled.py +248 -0
  291. hatchet_sdk/v0/hatchet.py +310 -0
  292. hatchet_sdk/v0/labels.py +10 -0
  293. hatchet_sdk/v0/logger.py +13 -0
  294. hatchet_sdk/v0/metadata.py +2 -0
  295. hatchet_sdk/v0/opentelemetry/instrumentor.py +396 -0
  296. hatchet_sdk/v0/rate_limit.py +126 -0
  297. hatchet_sdk/v0/token.py +27 -0
  298. hatchet_sdk/v0/utils/aio_utils.py +137 -0
  299. hatchet_sdk/v0/utils/backoff.py +9 -0
  300. hatchet_sdk/v0/utils/typing.py +12 -0
  301. hatchet_sdk/{v2 → v0/v2}/callable.py +8 -8
  302. hatchet_sdk/{v2 → v0/v2}/concurrency.py +2 -2
  303. hatchet_sdk/{v2 → v0/v2}/hatchet.py +10 -10
  304. hatchet_sdk/v0/worker/__init__.py +1 -0
  305. hatchet_sdk/v0/worker/action_listener_process.py +294 -0
  306. hatchet_sdk/v0/worker/runner/run_loop_manager.py +112 -0
  307. hatchet_sdk/v0/worker/runner/runner.py +460 -0
  308. hatchet_sdk/v0/worker/runner/utils/capture_logs.py +81 -0
  309. hatchet_sdk/v0/worker/worker.py +391 -0
  310. hatchet_sdk/{workflow.py → v0/workflow.py} +4 -4
  311. hatchet_sdk/v0/workflow_run.py +59 -0
  312. hatchet_sdk/waits.py +120 -0
  313. hatchet_sdk/worker/__init__.py +0 -1
  314. hatchet_sdk/worker/action_listener_process.py +80 -55
  315. hatchet_sdk/worker/runner/run_loop_manager.py +46 -34
  316. hatchet_sdk/worker/runner/runner.py +82 -87
  317. hatchet_sdk/worker/runner/utils/capture_logs.py +26 -23
  318. hatchet_sdk/worker/worker.py +172 -149
  319. hatchet_sdk/workflow_run.py +7 -21
  320. {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/METADATA +2 -2
  321. hatchet_sdk-1.0.0a1.dist-info/RECORD +505 -0
  322. {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/entry_points.txt +2 -0
  323. hatchet_sdk/utils/serialization.py +0 -18
  324. hatchet_sdk-0.47.1.dist-info/RECORD +0 -237
  325. /hatchet_sdk/{loader.py → v0/loader.py} +0 -0
  326. /hatchet_sdk/{semver.py → v0/semver.py} +0 -0
  327. /hatchet_sdk/{utils → v0/utils}/types.py +0 -0
  328. /hatchet_sdk/{worker → v0/worker}/runner/utils/error_with_traceback.py +0 -0
  329. {hatchet_sdk-0.47.1.dist-info → hatchet_sdk-1.0.0a1.dist-info}/WHEEL +0 -0
@@ -1,9 +1,12 @@
1
1
  import asyncio
2
2
  import json
3
- from typing import AsyncGenerator
3
+ from enum import Enum
4
+ from typing import Any, AsyncGenerator, Callable, Generator, cast
4
5
 
5
6
  import grpc
7
+ from pydantic import BaseModel
6
8
 
9
+ from hatchet_sdk.config import ClientConfig
7
10
  from hatchet_sdk.connection import new_conn
8
11
  from hatchet_sdk.contracts.dispatcher_pb2 import (
9
12
  RESOURCE_TYPE_STEP_RUN,
@@ -13,15 +16,13 @@ from hatchet_sdk.contracts.dispatcher_pb2 import (
13
16
  WorkflowEvent,
14
17
  )
15
18
  from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
16
-
17
- from ..loader import ClientConfig
18
- from ..metadata import get_metadata
19
+ from hatchet_sdk.metadata import get_metadata
19
20
 
20
21
  DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5 # seconds
21
22
  DEFAULT_ACTION_LISTENER_RETRY_COUNT = 5
22
23
 
23
24
 
24
- class StepRunEventType:
25
+ class StepRunEventType(str, Enum):
25
26
  STEP_RUN_EVENT_TYPE_STARTED = "STEP_RUN_EVENT_TYPE_STARTED"
26
27
  STEP_RUN_EVENT_TYPE_COMPLETED = "STEP_RUN_EVENT_TYPE_COMPLETED"
27
28
  STEP_RUN_EVENT_TYPE_FAILED = "STEP_RUN_EVENT_TYPE_FAILED"
@@ -30,7 +31,7 @@ class StepRunEventType:
30
31
  STEP_RUN_EVENT_TYPE_STREAM = "STEP_RUN_EVENT_TYPE_STREAM"
31
32
 
32
33
 
33
- class WorkflowRunEventType:
34
+ class WorkflowRunEventType(str, Enum):
34
35
  WORKFLOW_RUN_EVENT_TYPE_STARTED = "WORKFLOW_RUN_EVENT_TYPE_STARTED"
35
36
  WORKFLOW_RUN_EVENT_TYPE_COMPLETED = "WORKFLOW_RUN_EVENT_TYPE_COMPLETED"
36
37
  WORKFLOW_RUN_EVENT_TYPE_FAILED = "WORKFLOW_RUN_EVENT_TYPE_FAILED"
@@ -56,50 +57,36 @@ workflow_run_event_type_mapping = {
56
57
  }
57
58
 
58
59
 
59
- class StepRunEvent:
60
- def __init__(self, type: StepRunEventType, payload: str):
61
- self.type = type
62
- self.payload = payload
63
-
64
-
65
- def new_listener(config: ClientConfig):
66
- return RunEventListenerClient(config=config)
60
+ class StepRunEvent(BaseModel):
61
+ type: StepRunEventType
62
+ payload: str
67
63
 
68
64
 
69
65
  class RunEventListener:
70
-
71
- workflow_run_id: str = None
72
- additional_meta_kv: tuple[str, str] = None
73
-
74
- def __init__(self, client: DispatcherStub, token: str):
66
+ def __init__(
67
+ self,
68
+ client: DispatcherStub,
69
+ token: str,
70
+ workflow_run_id: str | None = None,
71
+ additional_meta_kv: tuple[str, str] | None = None,
72
+ ):
75
73
  self.client = client
76
74
  self.stop_signal = False
77
75
  self.token = token
78
76
 
79
- @classmethod
80
- def for_run_id(cls, workflow_run_id: str, client: DispatcherStub, token: str):
81
- listener = RunEventListener(client, token)
82
- listener.workflow_run_id = workflow_run_id
83
- return listener
77
+ self.workflow_run_id = workflow_run_id
78
+ self.additional_meta_kv = additional_meta_kv
84
79
 
85
- @classmethod
86
- def for_additional_meta(
87
- cls, key: str, value: str, client: DispatcherStub, token: str
88
- ):
89
- listener = RunEventListener(client, token)
90
- listener.additional_meta_kv = (key, value)
91
- return listener
92
-
93
- def abort(self):
80
+ def abort(self) -> None:
94
81
  self.stop_signal = True
95
82
 
96
- def __aiter__(self):
83
+ def __aiter__(self) -> AsyncGenerator[StepRunEvent, None]:
97
84
  return self._generator()
98
85
 
99
- async def __anext__(self):
86
+ async def __anext__(self) -> StepRunEvent:
100
87
  return await self._generator().__anext__()
101
88
 
102
- def __iter__(self):
89
+ def __iter__(self) -> Generator[StepRunEvent, None, None]:
103
90
  try:
104
91
  loop = asyncio.get_event_loop()
105
92
  except RuntimeError as e:
@@ -146,14 +133,16 @@ class RunEventListener:
146
133
  try:
147
134
  if workflow_event.eventPayload:
148
135
  payload = json.loads(workflow_event.eventPayload)
149
- except Exception as e:
136
+ except Exception:
150
137
  payload = workflow_event.eventPayload
151
138
  pass
152
139
 
140
+ assert isinstance(payload, str)
141
+
153
142
  yield StepRunEvent(type=eventType, payload=payload)
154
143
  elif workflow_event.resourceType == RESOURCE_TYPE_WORKFLOW_RUN:
155
- if workflow_event.eventType in workflow_run_event_type_mapping:
156
- eventType = workflow_run_event_type_mapping[
144
+ if workflow_event.eventType in step_run_event_type_mapping:
145
+ workflowRunEventType = step_run_event_type_mapping[
157
146
  workflow_event.eventType
158
147
  ]
159
148
  else:
@@ -166,10 +155,12 @@ class RunEventListener:
166
155
  try:
167
156
  if workflow_event.eventPayload:
168
157
  payload = json.loads(workflow_event.eventPayload)
169
- except Exception as e:
158
+ except Exception:
170
159
  pass
171
160
 
172
- yield StepRunEvent(type=eventType, payload=payload)
161
+ assert isinstance(payload, str)
162
+
163
+ yield StepRunEvent(type=workflowRunEventType, payload=payload)
173
164
 
174
165
  if workflow_event.hangup:
175
166
  listener = None
@@ -194,7 +185,7 @@ class RunEventListener:
194
185
  break
195
186
  # Raise StopAsyncIteration to properly end the generator
196
187
 
197
- async def retry_subscribe(self):
188
+ async def retry_subscribe(self) -> AsyncGenerator[WorkflowEvent, None]:
198
189
  retries = 0
199
190
 
200
191
  while retries < DEFAULT_ACTION_LISTENER_RETRY_COUNT:
@@ -203,19 +194,25 @@ class RunEventListener:
203
194
  await asyncio.sleep(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL)
204
195
 
205
196
  if self.workflow_run_id is not None:
206
- return self.client.SubscribeToWorkflowEvents(
207
- SubscribeToWorkflowEventsRequest(
208
- workflowRunId=self.workflow_run_id,
197
+ return cast(
198
+ AsyncGenerator[WorkflowEvent, None],
199
+ self.client.SubscribeToWorkflowEvents(
200
+ SubscribeToWorkflowEventsRequest(
201
+ workflowRunId=self.workflow_run_id,
202
+ ),
203
+ metadata=get_metadata(self.token),
209
204
  ),
210
- metadata=get_metadata(self.token),
211
205
  )
212
206
  elif self.additional_meta_kv is not None:
213
- return self.client.SubscribeToWorkflowEvents(
214
- SubscribeToWorkflowEventsRequest(
215
- additionalMetaKey=self.additional_meta_kv[0],
216
- additionalMetaValue=self.additional_meta_kv[1],
207
+ return cast(
208
+ AsyncGenerator[WorkflowEvent, None],
209
+ self.client.SubscribeToWorkflowEvents(
210
+ SubscribeToWorkflowEventsRequest(
211
+ additionalMetaKey=self.additional_meta_kv[0],
212
+ additionalMetaValue=self.additional_meta_kv[1],
213
+ ),
214
+ metadata=get_metadata(self.token),
217
215
  ),
218
- metadata=get_metadata(self.token),
219
216
  )
220
217
  else:
221
218
  raise Exception("no listener method provided")
@@ -226,34 +223,42 @@ class RunEventListener:
226
223
  else:
227
224
  raise ValueError(f"gRPC error: {e}")
228
225
 
226
+ raise Exception("Failed to subscribe to workflow events")
227
+
229
228
 
230
229
  class RunEventListenerClient:
231
230
  def __init__(self, config: ClientConfig):
232
231
  self.token = config.token
233
232
  self.config = config
234
- self.client: DispatcherStub = None
233
+ self.client: DispatcherStub | None = None
235
234
 
236
- def stream_by_run_id(self, workflow_run_id: str):
235
+ def stream_by_run_id(self, workflow_run_id: str) -> RunEventListener:
237
236
  return self.stream(workflow_run_id)
238
237
 
239
- def stream(self, workflow_run_id: str):
238
+ def stream(self, workflow_run_id: str) -> RunEventListener:
240
239
  if not isinstance(workflow_run_id, str) and hasattr(workflow_run_id, "__str__"):
241
240
  workflow_run_id = str(workflow_run_id)
242
241
 
243
242
  if not self.client:
244
243
  aio_conn = new_conn(self.config, True)
245
- self.client = DispatcherStub(aio_conn)
244
+ self.client = DispatcherStub(aio_conn) # type: ignore[no-untyped-call]
246
245
 
247
- return RunEventListener.for_run_id(workflow_run_id, self.client, self.token)
246
+ return RunEventListener(
247
+ client=self.client, token=self.token, workflow_run_id=workflow_run_id
248
+ )
248
249
 
249
- def stream_by_additional_metadata(self, key: str, value: str):
250
+ def stream_by_additional_metadata(self, key: str, value: str) -> RunEventListener:
250
251
  if not self.client:
251
252
  aio_conn = new_conn(self.config, True)
252
- self.client = DispatcherStub(aio_conn)
253
+ self.client = DispatcherStub(aio_conn) # type: ignore[no-untyped-call]
253
254
 
254
- return RunEventListener.for_additional_meta(key, value, self.client, self.token)
255
+ return RunEventListener(
256
+ client=self.client, token=self.token, additional_meta_kv=(key, value)
257
+ )
255
258
 
256
- async def on(self, workflow_run_id: str, handler: callable = None):
259
+ async def on(
260
+ self, workflow_run_id: str, handler: Callable[[StepRunEvent], Any] | None = None
261
+ ) -> None:
257
262
  async for event in self.stream(workflow_run_id):
258
263
  # call the handler if provided
259
264
  if handler:
@@ -1,22 +1,22 @@
1
1
  import asyncio
2
2
  import json
3
3
  from collections.abc import AsyncIterator
4
- from typing import AsyncGenerator
4
+ from typing import Any, cast
5
5
 
6
6
  import grpc
7
- from grpc._cython import cygrpc
7
+ import grpc.aio
8
+ from grpc._cython import cygrpc # type: ignore[attr-defined]
8
9
 
9
- from hatchet_sdk.clients.event_ts import Event_ts, read_with_interrupt
10
+ from hatchet_sdk.clients.event_ts import ThreadSafeEvent, read_with_interrupt
11
+ from hatchet_sdk.config import ClientConfig
10
12
  from hatchet_sdk.connection import new_conn
11
13
  from hatchet_sdk.contracts.dispatcher_pb2 import (
12
14
  SubscribeToWorkflowRunsRequest,
13
15
  WorkflowRunEvent,
14
16
  )
15
17
  from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
16
-
17
- from ..loader import ClientConfig
18
- from ..logger import logger
19
- from ..metadata import get_metadata
18
+ from hatchet_sdk.logger import logger
19
+ from hatchet_sdk.metadata import get_metadata
20
20
 
21
21
  DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL = 3 # seconds
22
22
  DEFAULT_WORKFLOW_LISTENER_RETRY_COUNT = 5
@@ -31,10 +31,10 @@ class _Subscription:
31
31
  self.workflow_run_id = workflow_run_id
32
32
  self.queue: asyncio.Queue[WorkflowRunEvent | None] = asyncio.Queue()
33
33
 
34
- async def __aiter__(self):
34
+ async def __aiter__(self) -> "_Subscription":
35
35
  return self
36
36
 
37
- async def __anext__(self) -> WorkflowRunEvent:
37
+ async def __anext__(self) -> WorkflowRunEvent | None:
38
38
  return await self.queue.get()
39
39
 
40
40
  async def get(self) -> WorkflowRunEvent:
@@ -45,35 +45,14 @@ class _Subscription:
45
45
 
46
46
  return event
47
47
 
48
- async def put(self, item: WorkflowRunEvent):
48
+ async def put(self, item: WorkflowRunEvent) -> None:
49
49
  await self.queue.put(item)
50
50
 
51
- async def close(self):
51
+ async def close(self) -> None:
52
52
  await self.queue.put(None)
53
53
 
54
54
 
55
55
  class PooledWorkflowRunListener:
56
- # list of all active subscriptions, mapping from a subscription id to a workflow run id
57
- subscriptionsToWorkflows: dict[int, str] = {}
58
-
59
- # list of workflow run ids mapped to an array of subscription ids
60
- workflowsToSubscriptions: dict[str, list[int]] = {}
61
-
62
- subscription_counter: int = 0
63
- subscription_counter_lock: asyncio.Lock = asyncio.Lock()
64
-
65
- requests: asyncio.Queue[SubscribeToWorkflowRunsRequest] = asyncio.Queue()
66
-
67
- listener: AsyncGenerator[WorkflowRunEvent, None] = None
68
- listener_task: asyncio.Task = None
69
-
70
- curr_requester: int = 0
71
-
72
- # events have keys of the format workflow_run_id + subscription_id
73
- events: dict[int, _Subscription] = {}
74
-
75
- interrupter: asyncio.Task = None
76
-
77
56
  def __init__(self, config: ClientConfig):
78
57
  try:
79
58
  asyncio.get_running_loop()
@@ -82,11 +61,37 @@ class PooledWorkflowRunListener:
82
61
  asyncio.set_event_loop(loop)
83
62
 
84
63
  conn = new_conn(config, True)
85
- self.client = DispatcherStub(conn)
64
+ self.client = DispatcherStub(conn) # type: ignore[no-untyped-call]
86
65
  self.token = config.token
87
66
  self.config = config
88
67
 
89
- async def _interrupter(self):
68
+ # list of all active subscriptions, mapping from a subscription id to a workflow run id
69
+ self.subscriptions_to_workflows: dict[int, str] = {}
70
+
71
+ # list of workflow run ids mapped to an array of subscription ids
72
+ self.workflows_to_subscriptions: dict[str, list[int]] = {}
73
+
74
+ self.subscription_counter: int = 0
75
+ self.subscription_counter_lock: asyncio.Lock = asyncio.Lock()
76
+
77
+ self.requests: asyncio.Queue[SubscribeToWorkflowRunsRequest | int] = (
78
+ asyncio.Queue()
79
+ )
80
+
81
+ self.listener: (
82
+ grpc.aio.UnaryStreamCall[SubscribeToWorkflowRunsRequest, WorkflowRunEvent]
83
+ | None
84
+ ) = None
85
+ self.listener_task: asyncio.Task[None] | None = None
86
+
87
+ self.curr_requester: int = 0
88
+
89
+ # events have keys of the format workflow_run_id + subscription_id
90
+ self.events: dict[int, _Subscription] = {}
91
+
92
+ self.interrupter: asyncio.Task[None] | None = None
93
+
94
+ async def _interrupter(self) -> None:
90
95
  """
91
96
  _interrupter runs in a separate thread and interrupts the listener according to a configurable duration.
92
97
  """
@@ -95,7 +100,7 @@ class PooledWorkflowRunListener:
95
100
  if self.interrupt is not None:
96
101
  self.interrupt.set()
97
102
 
98
- async def _init_producer(self):
103
+ async def _init_producer(self) -> None:
99
104
  try:
100
105
  if not self.listener:
101
106
  while True:
@@ -111,7 +116,10 @@ class PooledWorkflowRunListener:
111
116
  self.interrupter = asyncio.create_task(self._interrupter())
112
117
 
113
118
  while True:
114
- self.interrupt = Event_ts()
119
+ self.interrupt = ThreadSafeEvent()
120
+ if self.listener is None:
121
+ continue
122
+
115
123
  t = asyncio.create_task(
116
124
  read_with_interrupt(self.listener, self.interrupt)
117
125
  )
@@ -124,7 +132,8 @@ class PooledWorkflowRunListener:
124
132
  )
125
133
 
126
134
  t.cancel()
127
- self.listener.cancel()
135
+ if self.listener:
136
+ self.listener.cancel()
128
137
  await asyncio.sleep(
129
138
  DEFAULT_WORKFLOW_LISTENER_RETRY_INTERVAL
130
139
  )
@@ -136,7 +145,7 @@ class PooledWorkflowRunListener:
136
145
  break
137
146
 
138
147
  # get a list of subscriptions for this workflow
139
- subscriptions = self.workflowsToSubscriptions.get(
148
+ subscriptions = self.workflows_to_subscriptions.get(
140
149
  workflow_event.workflowRunId, []
141
150
  )
142
151
 
@@ -163,7 +172,7 @@ class PooledWorkflowRunListener:
163
172
  self.curr_requester = self.curr_requester + 1
164
173
 
165
174
  # replay all existing subscriptions
166
- workflow_run_set = set(self.subscriptionsToWorkflows.values())
175
+ workflow_run_set = set(self.subscriptions_to_workflows.values())
167
176
 
168
177
  for workflow_run_id in workflow_run_set:
169
178
  yield SubscribeToWorkflowRunsRequest(
@@ -184,17 +193,16 @@ class PooledWorkflowRunListener:
184
193
  yield request
185
194
  self.requests.task_done()
186
195
 
187
- def cleanup_subscription(self, subscription_id: int):
188
- workflow_run_id = self.subscriptionsToWorkflows[subscription_id]
196
+ def cleanup_subscription(self, subscription_id: int) -> None:
197
+ workflow_run_id = self.subscriptions_to_workflows[subscription_id]
189
198
 
190
- if workflow_run_id in self.workflowsToSubscriptions:
191
- self.workflowsToSubscriptions[workflow_run_id].remove(subscription_id)
199
+ if workflow_run_id in self.workflows_to_subscriptions:
200
+ self.workflows_to_subscriptions[workflow_run_id].remove(subscription_id)
192
201
 
193
- del self.subscriptionsToWorkflows[subscription_id]
202
+ del self.subscriptions_to_workflows[subscription_id]
194
203
  del self.events[subscription_id]
195
204
 
196
- async def subscribe(self, workflow_run_id: str):
197
- init_producer: asyncio.Task = None
205
+ async def subscribe(self, workflow_run_id: str) -> WorkflowRunEvent:
198
206
  try:
199
207
  # create a new subscription id, place a mutex on the counter
200
208
  await self.subscription_counter_lock.acquire()
@@ -202,12 +210,12 @@ class PooledWorkflowRunListener:
202
210
  subscription_id = self.subscription_counter
203
211
  self.subscription_counter_lock.release()
204
212
 
205
- self.subscriptionsToWorkflows[subscription_id] = workflow_run_id
213
+ self.subscriptions_to_workflows[subscription_id] = workflow_run_id
206
214
 
207
- if workflow_run_id not in self.workflowsToSubscriptions:
208
- self.workflowsToSubscriptions[workflow_run_id] = [subscription_id]
215
+ if workflow_run_id not in self.workflows_to_subscriptions:
216
+ self.workflows_to_subscriptions[workflow_run_id] = [subscription_id]
209
217
  else:
210
- self.workflowsToSubscriptions[workflow_run_id].append(subscription_id)
218
+ self.workflows_to_subscriptions[workflow_run_id].append(subscription_id)
211
219
 
212
220
  self.events[subscription_id] = _Subscription(
213
221
  subscription_id, workflow_run_id
@@ -222,23 +230,17 @@ class PooledWorkflowRunListener:
222
230
  if not self.listener_task or self.listener_task.done():
223
231
  self.listener_task = asyncio.create_task(self._init_producer())
224
232
 
225
- event = await self.events[subscription_id].get()
226
-
227
- return event
233
+ return await self.events[subscription_id].get()
228
234
  except asyncio.CancelledError:
229
235
  raise
230
236
  finally:
231
237
  self.cleanup_subscription(subscription_id)
232
238
 
233
- async def result(self, workflow_run_id: str):
239
+ async def result(self, workflow_run_id: str) -> dict[str, Any]:
234
240
  from hatchet_sdk.clients.admin import DedupeViolationErr
235
241
 
236
242
  event = await self.subscribe(workflow_run_id)
237
-
238
- errors = []
239
-
240
- if event.results:
241
- errors = [result.error for result in event.results if result.error]
243
+ errors = [result.error for result in event.results if result.error]
242
244
 
243
245
  if errors:
244
246
  if DEDUPE_MESSAGE in errors[0]:
@@ -246,15 +248,15 @@ class PooledWorkflowRunListener:
246
248
  else:
247
249
  raise Exception(f"Workflow Errors: {errors}")
248
250
 
249
- results = {
251
+ return {
250
252
  result.stepReadableId: json.loads(result.output)
251
253
  for result in event.results
252
254
  if result.output
253
255
  }
254
256
 
255
- return results
256
-
257
- async def _retry_subscribe(self):
257
+ async def _retry_subscribe(
258
+ self,
259
+ ) -> grpc.aio.UnaryStreamCall[SubscribeToWorkflowRunsRequest, WorkflowRunEvent]:
258
260
  retries = 0
259
261
 
260
262
  while retries < DEFAULT_WORKFLOW_LISTENER_RETRY_COUNT:
@@ -266,12 +268,19 @@ class PooledWorkflowRunListener:
266
268
  if self.curr_requester != 0:
267
269
  self.requests.put_nowait(self.curr_requester)
268
270
 
269
- return self.client.SubscribeToWorkflowRuns(
270
- self._request(),
271
- metadata=get_metadata(self.token),
271
+ return cast(
272
+ grpc.aio.UnaryStreamCall[
273
+ SubscribeToWorkflowRunsRequest, WorkflowRunEvent
274
+ ],
275
+ self.client.SubscribeToWorkflowRuns(
276
+ self._request(),
277
+ metadata=get_metadata(self.token),
278
+ ),
272
279
  )
273
280
  except grpc.RpcError as e:
274
281
  if e.code() == grpc.StatusCode.UNAVAILABLE:
275
282
  retries = retries + 1
276
283
  else:
277
284
  raise ValueError(f"gRPC error: {e}")
285
+
286
+ raise ValueError("Failed to connect to workflow run listener")
hatchet_sdk/config.py ADDED
@@ -0,0 +1,117 @@
1
+ import json
2
+ from logging import Logger, getLogger
3
+
4
+ from pydantic import Field, field_validator, model_validator
5
+ from pydantic_settings import BaseSettings, SettingsConfigDict
6
+
7
+ from hatchet_sdk.token import get_addresses_from_jwt, get_tenant_id_from_jwt
8
+
9
+
10
+ def create_settings_config(env_prefix: str) -> SettingsConfigDict:
11
+ return SettingsConfigDict(
12
+ env_prefix=env_prefix,
13
+ env_file=(".env", ".env.hatchet", ".env.dev", ".env.local"),
14
+ extra="ignore",
15
+ )
16
+
17
+
18
+ class ClientTLSConfig(BaseSettings):
19
+ model_config = create_settings_config(
20
+ env_prefix="HATCHET_CLIENT_TLS_",
21
+ )
22
+
23
+ strategy: str = "tls"
24
+ cert_file: str | None = None
25
+ key_file: str | None = None
26
+ root_ca_file: str | None = None
27
+ server_name: str = ""
28
+
29
+
30
+ class HealthcheckConfig(BaseSettings):
31
+ model_config = create_settings_config(
32
+ env_prefix="HATCHET_CLIENT_WORKER_HEALTHCHECK_",
33
+ )
34
+
35
+ port: int = 8001
36
+ enabled: bool = False
37
+
38
+
39
+ DEFAULT_HOST_PORT = "localhost:7070"
40
+
41
+
42
+ class ClientConfig(BaseSettings):
43
+ model_config = create_settings_config(
44
+ env_prefix="HATCHET_CLIENT_",
45
+ )
46
+
47
+ token: str = ""
48
+ logger: Logger = getLogger()
49
+
50
+ tenant_id: str = ""
51
+ host_port: str = DEFAULT_HOST_PORT
52
+ server_url: str = "https://app.dev.hatchet-tools.com"
53
+ namespace: str = ""
54
+
55
+ tls_config: ClientTLSConfig = Field(default_factory=lambda: ClientTLSConfig())
56
+ healthcheck: HealthcheckConfig = Field(default_factory=lambda: HealthcheckConfig())
57
+
58
+ listener_v2_timeout: int | None = None
59
+ grpc_max_recv_message_length: int = Field(
60
+ default=4 * 1024 * 1024, description="4MB default"
61
+ )
62
+ grpc_max_send_message_length: int = Field(
63
+ default=4 * 1024 * 1024, description="4MB default"
64
+ )
65
+
66
+ worker_preset_labels: dict[str, str] = Field(default_factory=dict)
67
+ enable_force_kill_sync_threads: bool = False
68
+
69
+ @model_validator(mode="after")
70
+ def validate_token_and_tenant(self) -> "ClientConfig":
71
+ if not self.token:
72
+ raise ValueError("Token must be set")
73
+
74
+ if not self.tenant_id:
75
+ self.tenant_id = get_tenant_id_from_jwt(self.token)
76
+
77
+ return self
78
+
79
+ @model_validator(mode="after")
80
+ def validate_addresses(self) -> "ClientConfig":
81
+ if self.host_port == DEFAULT_HOST_PORT:
82
+ server_url, grpc_broadcast_address = get_addresses_from_jwt(self.token)
83
+ self.host_port = grpc_broadcast_address
84
+ self.server_url = server_url
85
+ else:
86
+ self.server_url = self.host_port
87
+
88
+ if not self.tls_config.server_name:
89
+ self.tls_config.server_name = self.host_port.split(":")[0]
90
+
91
+ if not self.tls_config.server_name:
92
+ self.tls_config.server_name = "localhost"
93
+
94
+ return self
95
+
96
+ @field_validator("listener_v2_timeout")
97
+ @classmethod
98
+ def validate_listener_timeout(cls, value: int | None | str) -> int | None:
99
+ if value is None:
100
+ return None
101
+
102
+ if isinstance(value, int):
103
+ return value
104
+
105
+ return int(value)
106
+
107
+ @field_validator("namespace")
108
+ @classmethod
109
+ def validate_namespace(cls, namespace: str) -> str:
110
+ if not namespace:
111
+ return ""
112
+ if not namespace.endswith("_"):
113
+ namespace = f"{namespace}_"
114
+ return namespace.lower()
115
+
116
+ def __hash__(self) -> int:
117
+ return hash(json.dumps(self.model_dump(), default=str))