hatchet-sdk 0.46.1__py3-none-any.whl → 1.0.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.
Files changed (303) hide show
  1. hatchet_sdk/__init__.py +25 -16
  2. hatchet_sdk/client.py +14 -39
  3. hatchet_sdk/clients/admin.py +203 -362
  4. hatchet_sdk/clients/dispatcher/action_listener.py +106 -84
  5. hatchet_sdk/clients/dispatcher/dispatcher.py +21 -21
  6. hatchet_sdk/clients/event_ts.py +23 -10
  7. hatchet_sdk/clients/events.py +96 -99
  8. hatchet_sdk/clients/rest/__init__.py +24 -0
  9. hatchet_sdk/clients/rest/api/__init__.py +2 -0
  10. hatchet_sdk/clients/rest/api/task_api.py +2174 -0
  11. hatchet_sdk/clients/rest/api/workflow_runs_api.py +638 -106
  12. hatchet_sdk/clients/rest/api_client.py +1 -1
  13. hatchet_sdk/clients/rest/configuration.py +8 -1
  14. hatchet_sdk/clients/rest/exceptions.py +21 -0
  15. hatchet_sdk/clients/rest/models/__init__.py +22 -0
  16. hatchet_sdk/clients/rest/models/tenant.py +4 -0
  17. hatchet_sdk/clients/rest/models/tenant_version.py +37 -0
  18. hatchet_sdk/clients/rest/models/update_tenant_request.py +7 -0
  19. hatchet_sdk/clients/rest/models/v1_cancel_task_request.py +104 -0
  20. hatchet_sdk/clients/rest/models/v1_dag_children.py +102 -0
  21. hatchet_sdk/clients/rest/models/v1_replay_task_request.py +104 -0
  22. hatchet_sdk/clients/rest/models/v1_task.py +174 -0
  23. hatchet_sdk/clients/rest/models/v1_task_event.py +118 -0
  24. hatchet_sdk/clients/rest/models/v1_task_event_list.py +110 -0
  25. hatchet_sdk/clients/rest/models/v1_task_event_type.py +55 -0
  26. hatchet_sdk/clients/rest/models/v1_task_filter.py +106 -0
  27. hatchet_sdk/clients/rest/models/v1_task_point_metric.py +92 -0
  28. hatchet_sdk/clients/rest/models/v1_task_point_metrics.py +100 -0
  29. hatchet_sdk/clients/rest/models/v1_task_run_metric.py +88 -0
  30. hatchet_sdk/clients/rest/models/v1_task_run_status.py +40 -0
  31. hatchet_sdk/clients/rest/models/v1_task_status.py +40 -0
  32. hatchet_sdk/clients/rest/models/v1_task_summary.py +212 -0
  33. hatchet_sdk/clients/rest/models/v1_task_summary_list.py +110 -0
  34. hatchet_sdk/clients/rest/models/v1_workflow_run.py +171 -0
  35. hatchet_sdk/clients/rest/models/v1_workflow_run_details.py +145 -0
  36. hatchet_sdk/clients/rest/models/v1_workflow_type.py +37 -0
  37. hatchet_sdk/clients/rest/models/workflow_run_shape_item_for_workflow_run_details.py +99 -0
  38. hatchet_sdk/clients/rest/rest.py +37 -26
  39. hatchet_sdk/clients/rest/tenacity_utils.py +1 -1
  40. hatchet_sdk/clients/rest_client.py +141 -116
  41. hatchet_sdk/clients/run_event_listener.py +66 -60
  42. hatchet_sdk/clients/workflow_listener.py +77 -64
  43. hatchet_sdk/config.py +117 -0
  44. hatchet_sdk/connection.py +27 -13
  45. hatchet_sdk/context/__init__.py +0 -1
  46. hatchet_sdk/context/context.py +143 -202
  47. hatchet_sdk/features/cron.py +43 -57
  48. hatchet_sdk/features/scheduled.py +60 -74
  49. hatchet_sdk/hatchet.py +192 -195
  50. hatchet_sdk/labels.py +4 -6
  51. hatchet_sdk/metadata.py +1 -1
  52. hatchet_sdk/opentelemetry/instrumentor.py +112 -35
  53. hatchet_sdk/rate_limit.py +9 -18
  54. hatchet_sdk/token.py +13 -9
  55. hatchet_sdk/utils/aio_utils.py +0 -40
  56. hatchet_sdk/utils/proto_enums.py +54 -0
  57. hatchet_sdk/utils/typing.py +9 -1
  58. hatchet_sdk/v0/__init__.py +251 -0
  59. hatchet_sdk/v0/client.py +119 -0
  60. hatchet_sdk/v0/clients/admin.py +541 -0
  61. hatchet_sdk/v0/clients/dispatcher/action_listener.py +422 -0
  62. hatchet_sdk/v0/clients/dispatcher/dispatcher.py +204 -0
  63. hatchet_sdk/v0/clients/event_ts.py +28 -0
  64. hatchet_sdk/v0/clients/events.py +182 -0
  65. hatchet_sdk/v0/clients/rest/__init__.py +307 -0
  66. hatchet_sdk/v0/clients/rest/api/__init__.py +19 -0
  67. hatchet_sdk/v0/clients/rest/api/api_token_api.py +858 -0
  68. hatchet_sdk/v0/clients/rest/api/default_api.py +2259 -0
  69. hatchet_sdk/v0/clients/rest/api/event_api.py +2548 -0
  70. hatchet_sdk/v0/clients/rest/api/github_api.py +331 -0
  71. hatchet_sdk/v0/clients/rest/api/healthcheck_api.py +483 -0
  72. hatchet_sdk/v0/clients/rest/api/log_api.py +449 -0
  73. hatchet_sdk/v0/clients/rest/api/metadata_api.py +728 -0
  74. hatchet_sdk/v0/clients/rest/api/rate_limits_api.py +423 -0
  75. hatchet_sdk/v0/clients/rest/api/slack_api.py +577 -0
  76. hatchet_sdk/v0/clients/rest/api/sns_api.py +872 -0
  77. hatchet_sdk/v0/clients/rest/api/step_run_api.py +2202 -0
  78. hatchet_sdk/v0/clients/rest/api/tenant_api.py +4430 -0
  79. hatchet_sdk/v0/clients/rest/api/user_api.py +2888 -0
  80. hatchet_sdk/v0/clients/rest/api/worker_api.py +858 -0
  81. hatchet_sdk/v0/clients/rest/api/workflow_api.py +6312 -0
  82. hatchet_sdk/v0/clients/rest/api/workflow_run_api.py +1932 -0
  83. hatchet_sdk/v0/clients/rest/api/workflow_runs_api.py +610 -0
  84. hatchet_sdk/v0/clients/rest/api_client.py +759 -0
  85. hatchet_sdk/v0/clients/rest/api_response.py +22 -0
  86. hatchet_sdk/v0/clients/rest/configuration.py +611 -0
  87. hatchet_sdk/v0/clients/rest/exceptions.py +200 -0
  88. hatchet_sdk/v0/clients/rest/models/__init__.py +274 -0
  89. hatchet_sdk/v0/clients/rest/models/accept_invite_request.py +83 -0
  90. hatchet_sdk/v0/clients/rest/models/api_error.py +102 -0
  91. hatchet_sdk/v0/clients/rest/models/api_errors.py +100 -0
  92. hatchet_sdk/v0/clients/rest/models/api_meta.py +144 -0
  93. hatchet_sdk/v0/clients/rest/models/api_meta_auth.py +85 -0
  94. hatchet_sdk/v0/clients/rest/models/api_meta_integration.py +88 -0
  95. hatchet_sdk/v0/clients/rest/models/api_meta_posthog.py +90 -0
  96. hatchet_sdk/v0/clients/rest/models/api_resource_meta.py +98 -0
  97. hatchet_sdk/v0/clients/rest/models/api_token.py +105 -0
  98. hatchet_sdk/v0/clients/rest/models/bulk_create_event_request.py +100 -0
  99. hatchet_sdk/v0/clients/rest/models/bulk_create_event_response.py +110 -0
  100. hatchet_sdk/v0/clients/rest/models/cancel_event_request.py +85 -0
  101. hatchet_sdk/v0/clients/rest/models/cancel_step_run_request.py +83 -0
  102. hatchet_sdk/v0/clients/rest/models/concurrency_limit_strategy.py +39 -0
  103. hatchet_sdk/v0/clients/rest/models/create_api_token_request.py +92 -0
  104. hatchet_sdk/v0/clients/rest/models/create_api_token_response.py +83 -0
  105. hatchet_sdk/v0/clients/rest/models/create_cron_workflow_trigger_request.py +98 -0
  106. hatchet_sdk/v0/clients/rest/models/create_event_request.py +95 -0
  107. hatchet_sdk/v0/clients/rest/models/create_pull_request_from_step_run.py +83 -0
  108. hatchet_sdk/v0/clients/rest/models/create_sns_integration_request.py +85 -0
  109. hatchet_sdk/v0/clients/rest/models/create_tenant_alert_email_group_request.py +83 -0
  110. hatchet_sdk/v0/clients/rest/models/create_tenant_invite_request.py +86 -0
  111. hatchet_sdk/v0/clients/rest/models/create_tenant_request.py +84 -0
  112. hatchet_sdk/v0/clients/rest/models/cron_workflows.py +131 -0
  113. hatchet_sdk/v0/clients/rest/models/cron_workflows_list.py +110 -0
  114. hatchet_sdk/v0/clients/rest/models/cron_workflows_method.py +37 -0
  115. hatchet_sdk/v0/clients/rest/models/cron_workflows_order_by_field.py +37 -0
  116. hatchet_sdk/v0/clients/rest/models/event.py +143 -0
  117. hatchet_sdk/v0/clients/rest/models/event_data.py +83 -0
  118. hatchet_sdk/v0/clients/rest/models/event_key_list.py +98 -0
  119. hatchet_sdk/v0/clients/rest/models/event_list.py +110 -0
  120. hatchet_sdk/v0/clients/rest/models/event_order_by_direction.py +37 -0
  121. hatchet_sdk/v0/clients/rest/models/event_order_by_field.py +36 -0
  122. hatchet_sdk/v0/clients/rest/models/event_update_cancel200_response.py +85 -0
  123. hatchet_sdk/v0/clients/rest/models/event_workflow_run_summary.py +116 -0
  124. hatchet_sdk/v0/clients/rest/models/events.py +110 -0
  125. hatchet_sdk/v0/clients/rest/models/get_step_run_diff_response.py +100 -0
  126. hatchet_sdk/v0/clients/rest/models/github_app_installation.py +107 -0
  127. hatchet_sdk/v0/clients/rest/models/github_branch.py +86 -0
  128. hatchet_sdk/v0/clients/rest/models/github_repo.py +86 -0
  129. hatchet_sdk/v0/clients/rest/models/info_get_version200_response.py +83 -0
  130. hatchet_sdk/v0/clients/rest/models/job.py +132 -0
  131. hatchet_sdk/v0/clients/rest/models/job_run.py +176 -0
  132. hatchet_sdk/v0/clients/rest/models/job_run_status.py +41 -0
  133. hatchet_sdk/v0/clients/rest/models/link_github_repository_request.py +106 -0
  134. hatchet_sdk/v0/clients/rest/models/list_api_tokens_response.py +110 -0
  135. hatchet_sdk/v0/clients/rest/models/list_github_app_installations_response.py +112 -0
  136. hatchet_sdk/v0/clients/rest/models/list_pull_requests_response.py +100 -0
  137. hatchet_sdk/v0/clients/rest/models/list_slack_webhooks.py +110 -0
  138. hatchet_sdk/v0/clients/rest/models/list_sns_integrations.py +110 -0
  139. hatchet_sdk/v0/clients/rest/models/log_line.py +94 -0
  140. hatchet_sdk/v0/clients/rest/models/log_line_level.py +39 -0
  141. hatchet_sdk/v0/clients/rest/models/log_line_list.py +110 -0
  142. hatchet_sdk/v0/clients/rest/models/log_line_order_by_direction.py +37 -0
  143. hatchet_sdk/v0/clients/rest/models/log_line_order_by_field.py +36 -0
  144. hatchet_sdk/v0/clients/rest/models/pagination_response.py +95 -0
  145. hatchet_sdk/v0/clients/rest/models/pull_request.py +112 -0
  146. hatchet_sdk/v0/clients/rest/models/pull_request_state.py +37 -0
  147. hatchet_sdk/v0/clients/rest/models/queue_metrics.py +97 -0
  148. hatchet_sdk/v0/clients/rest/models/rate_limit.py +117 -0
  149. hatchet_sdk/v0/clients/rest/models/rate_limit_list.py +110 -0
  150. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_direction.py +37 -0
  151. hatchet_sdk/v0/clients/rest/models/rate_limit_order_by_field.py +38 -0
  152. hatchet_sdk/v0/clients/rest/models/recent_step_runs.py +118 -0
  153. hatchet_sdk/v0/clients/rest/models/reject_invite_request.py +83 -0
  154. hatchet_sdk/v0/clients/rest/models/replay_event_request.py +85 -0
  155. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_request.py +85 -0
  156. hatchet_sdk/v0/clients/rest/models/replay_workflow_runs_response.py +100 -0
  157. hatchet_sdk/v0/clients/rest/models/rerun_step_run_request.py +83 -0
  158. hatchet_sdk/v0/clients/rest/models/schedule_workflow_run_request.py +92 -0
  159. hatchet_sdk/v0/clients/rest/models/scheduled_run_status.py +42 -0
  160. hatchet_sdk/v0/clients/rest/models/scheduled_workflows.py +149 -0
  161. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_list.py +110 -0
  162. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_method.py +37 -0
  163. hatchet_sdk/v0/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
  164. hatchet_sdk/v0/clients/rest/models/semaphore_slots.py +113 -0
  165. hatchet_sdk/v0/clients/rest/models/slack_webhook.py +127 -0
  166. hatchet_sdk/v0/clients/rest/models/sns_integration.py +114 -0
  167. hatchet_sdk/v0/clients/rest/models/step.py +123 -0
  168. hatchet_sdk/v0/clients/rest/models/step_run.py +202 -0
  169. hatchet_sdk/v0/clients/rest/models/step_run_archive.py +142 -0
  170. hatchet_sdk/v0/clients/rest/models/step_run_archive_list.py +110 -0
  171. hatchet_sdk/v0/clients/rest/models/step_run_diff.py +91 -0
  172. hatchet_sdk/v0/clients/rest/models/step_run_event.py +122 -0
  173. hatchet_sdk/v0/clients/rest/models/step_run_event_list.py +110 -0
  174. hatchet_sdk/v0/clients/rest/models/step_run_event_reason.py +52 -0
  175. hatchet_sdk/v0/clients/rest/models/step_run_event_severity.py +38 -0
  176. hatchet_sdk/v0/clients/rest/models/step_run_status.py +44 -0
  177. hatchet_sdk/v0/clients/rest/models/tenant.py +118 -0
  178. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group.py +98 -0
  179. hatchet_sdk/v0/clients/rest/models/tenant_alert_email_group_list.py +112 -0
  180. hatchet_sdk/v0/clients/rest/models/tenant_alerting_settings.py +143 -0
  181. hatchet_sdk/v0/clients/rest/models/tenant_invite.py +120 -0
  182. hatchet_sdk/v0/clients/rest/models/tenant_invite_list.py +110 -0
  183. hatchet_sdk/v0/clients/rest/models/tenant_list.py +110 -0
  184. hatchet_sdk/v0/clients/rest/models/tenant_member.py +123 -0
  185. hatchet_sdk/v0/clients/rest/models/tenant_member_list.py +110 -0
  186. hatchet_sdk/v0/clients/rest/models/tenant_member_role.py +38 -0
  187. hatchet_sdk/v0/clients/rest/models/tenant_queue_metrics.py +116 -0
  188. hatchet_sdk/v0/clients/rest/models/tenant_resource.py +40 -0
  189. hatchet_sdk/v0/clients/rest/models/tenant_resource_limit.py +135 -0
  190. hatchet_sdk/v0/clients/rest/models/tenant_resource_policy.py +102 -0
  191. hatchet_sdk/v0/clients/rest/models/tenant_step_run_queue_metrics.py +83 -0
  192. hatchet_sdk/v0/clients/rest/models/trigger_workflow_run_request.py +91 -0
  193. hatchet_sdk/v0/clients/rest/models/update_tenant_alert_email_group_request.py +83 -0
  194. hatchet_sdk/v0/clients/rest/models/update_tenant_invite_request.py +85 -0
  195. hatchet_sdk/v0/clients/rest/models/update_tenant_request.py +137 -0
  196. hatchet_sdk/v0/clients/rest/models/update_worker_request.py +87 -0
  197. hatchet_sdk/v0/clients/rest/models/user.py +126 -0
  198. hatchet_sdk/v0/clients/rest/models/user_change_password_request.py +88 -0
  199. hatchet_sdk/v0/clients/rest/models/user_login_request.py +86 -0
  200. hatchet_sdk/v0/clients/rest/models/user_register_request.py +91 -0
  201. hatchet_sdk/v0/clients/rest/models/user_tenant_memberships_list.py +110 -0
  202. hatchet_sdk/v0/clients/rest/models/user_tenant_public.py +86 -0
  203. hatchet_sdk/v0/clients/rest/models/webhook_worker.py +100 -0
  204. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_request.py +94 -0
  205. hatchet_sdk/v0/clients/rest/models/webhook_worker_create_response.py +98 -0
  206. hatchet_sdk/v0/clients/rest/models/webhook_worker_created.py +102 -0
  207. hatchet_sdk/v0/clients/rest/models/webhook_worker_list_response.py +110 -0
  208. hatchet_sdk/v0/clients/rest/models/webhook_worker_request.py +102 -0
  209. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_list_response.py +104 -0
  210. hatchet_sdk/v0/clients/rest/models/webhook_worker_request_method.py +38 -0
  211. hatchet_sdk/v0/clients/rest/models/worker.py +239 -0
  212. hatchet_sdk/v0/clients/rest/models/worker_label.py +102 -0
  213. hatchet_sdk/v0/clients/rest/models/worker_list.py +110 -0
  214. hatchet_sdk/v0/clients/rest/models/worker_runtime_info.py +103 -0
  215. hatchet_sdk/v0/clients/rest/models/worker_runtime_sdks.py +38 -0
  216. hatchet_sdk/v0/clients/rest/models/worker_type.py +38 -0
  217. hatchet_sdk/v0/clients/rest/models/workflow.py +165 -0
  218. hatchet_sdk/v0/clients/rest/models/workflow_concurrency.py +107 -0
  219. hatchet_sdk/v0/clients/rest/models/workflow_deployment_config.py +136 -0
  220. hatchet_sdk/v0/clients/rest/models/workflow_kind.py +38 -0
  221. hatchet_sdk/v0/clients/rest/models/workflow_list.py +120 -0
  222. hatchet_sdk/v0/clients/rest/models/workflow_metrics.py +97 -0
  223. hatchet_sdk/v0/clients/rest/models/workflow_run.py +188 -0
  224. hatchet_sdk/v0/clients/rest/models/workflow_run_cancel200_response.py +85 -0
  225. hatchet_sdk/v0/clients/rest/models/workflow_run_list.py +110 -0
  226. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_direction.py +37 -0
  227. hatchet_sdk/v0/clients/rest/models/workflow_run_order_by_field.py +39 -0
  228. hatchet_sdk/v0/clients/rest/models/workflow_run_shape.py +186 -0
  229. hatchet_sdk/v0/clients/rest/models/workflow_run_status.py +42 -0
  230. hatchet_sdk/v0/clients/rest/models/workflow_run_triggered_by.py +112 -0
  231. hatchet_sdk/v0/clients/rest/models/workflow_runs_cancel_request.py +85 -0
  232. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics.py +94 -0
  233. hatchet_sdk/v0/clients/rest/models/workflow_runs_metrics_counts.py +104 -0
  234. hatchet_sdk/v0/clients/rest/models/workflow_tag.py +84 -0
  235. hatchet_sdk/v0/clients/rest/models/workflow_trigger_cron_ref.py +86 -0
  236. hatchet_sdk/v0/clients/rest/models/workflow_trigger_event_ref.py +86 -0
  237. hatchet_sdk/v0/clients/rest/models/workflow_triggers.py +141 -0
  238. hatchet_sdk/v0/clients/rest/models/workflow_update_request.py +85 -0
  239. hatchet_sdk/v0/clients/rest/models/workflow_version.py +170 -0
  240. hatchet_sdk/v0/clients/rest/models/workflow_version_concurrency.py +114 -0
  241. hatchet_sdk/v0/clients/rest/models/workflow_version_definition.py +85 -0
  242. hatchet_sdk/v0/clients/rest/models/workflow_version_meta.py +123 -0
  243. hatchet_sdk/v0/clients/rest/models/workflow_workers_count.py +95 -0
  244. hatchet_sdk/v0/clients/rest/rest.py +187 -0
  245. hatchet_sdk/v0/clients/rest/tenacity_utils.py +39 -0
  246. hatchet_sdk/v0/clients/rest_client.py +613 -0
  247. hatchet_sdk/v0/clients/run_event_listener.py +260 -0
  248. hatchet_sdk/v0/clients/workflow_listener.py +277 -0
  249. hatchet_sdk/v0/connection.py +63 -0
  250. hatchet_sdk/v0/context/__init__.py +1 -0
  251. hatchet_sdk/v0/context/context.py +446 -0
  252. hatchet_sdk/v0/context/worker_context.py +28 -0
  253. hatchet_sdk/v0/contracts/dispatcher_pb2.py +102 -0
  254. hatchet_sdk/v0/contracts/dispatcher_pb2.pyi +387 -0
  255. hatchet_sdk/v0/contracts/dispatcher_pb2_grpc.py +621 -0
  256. hatchet_sdk/v0/contracts/events_pb2.py +46 -0
  257. hatchet_sdk/v0/contracts/events_pb2.pyi +87 -0
  258. hatchet_sdk/v0/contracts/events_pb2_grpc.py +274 -0
  259. hatchet_sdk/v0/contracts/workflows_pb2.py +80 -0
  260. hatchet_sdk/v0/contracts/workflows_pb2.pyi +312 -0
  261. hatchet_sdk/v0/contracts/workflows_pb2_grpc.py +277 -0
  262. hatchet_sdk/v0/features/cron.py +286 -0
  263. hatchet_sdk/v0/features/scheduled.py +248 -0
  264. hatchet_sdk/v0/hatchet.py +310 -0
  265. hatchet_sdk/v0/labels.py +10 -0
  266. hatchet_sdk/{loader.py → v0/loader.py} +11 -0
  267. hatchet_sdk/v0/logger.py +13 -0
  268. hatchet_sdk/v0/metadata.py +2 -0
  269. hatchet_sdk/v0/opentelemetry/instrumentor.py +396 -0
  270. hatchet_sdk/v0/rate_limit.py +126 -0
  271. hatchet_sdk/v0/semver.py +30 -0
  272. hatchet_sdk/v0/token.py +27 -0
  273. hatchet_sdk/v0/utils/aio_utils.py +137 -0
  274. hatchet_sdk/v0/utils/backoff.py +9 -0
  275. hatchet_sdk/v0/utils/typing.py +12 -0
  276. hatchet_sdk/{v2 → v0/v2}/callable.py +8 -8
  277. hatchet_sdk/{v2 → v0/v2}/concurrency.py +2 -2
  278. hatchet_sdk/{v2 → v0/v2}/hatchet.py +10 -10
  279. hatchet_sdk/v0/worker/__init__.py +1 -0
  280. hatchet_sdk/v0/worker/action_listener_process.py +278 -0
  281. hatchet_sdk/v0/worker/runner/run_loop_manager.py +112 -0
  282. hatchet_sdk/v0/worker/runner/runner.py +460 -0
  283. hatchet_sdk/v0/worker/runner/utils/capture_logs.py +81 -0
  284. hatchet_sdk/v0/worker/runner/utils/error_with_traceback.py +6 -0
  285. hatchet_sdk/v0/worker/worker.py +391 -0
  286. hatchet_sdk/v0/workflow.py +261 -0
  287. hatchet_sdk/v0/workflow_run.py +59 -0
  288. hatchet_sdk/worker/__init__.py +0 -1
  289. hatchet_sdk/worker/action_listener_process.py +36 -33
  290. hatchet_sdk/worker/runner/run_loop_manager.py +18 -16
  291. hatchet_sdk/worker/runner/runner.py +37 -59
  292. hatchet_sdk/worker/runner/utils/capture_logs.py +25 -14
  293. hatchet_sdk/worker/runner/utils/error_with_traceback.py +1 -1
  294. hatchet_sdk/worker/worker.py +61 -75
  295. hatchet_sdk/workflow.py +473 -207
  296. hatchet_sdk/workflow_run.py +14 -25
  297. {hatchet_sdk-0.46.1.dist-info → hatchet_sdk-1.0.0.dist-info}/METADATA +3 -2
  298. hatchet_sdk-1.0.0.dist-info/RECORD +485 -0
  299. {hatchet_sdk-0.46.1.dist-info → hatchet_sdk-1.0.0.dist-info}/entry_points.txt +1 -0
  300. hatchet_sdk/utils/serialization.py +0 -18
  301. hatchet_sdk-0.46.1.dist-info/RECORD +0 -237
  302. /hatchet_sdk/{utils → v0/utils}/types.py +0 -0
  303. {hatchet_sdk-0.46.1.dist-info → hatchet_sdk-1.0.0.dist-info}/WHEEL +0 -0
@@ -1 +0,0 @@
1
- from .worker import Worker, WorkerStartOptions, WorkerStatus
@@ -4,22 +4,22 @@ import signal
4
4
  import time
5
5
  from dataclasses import dataclass, field
6
6
  from multiprocessing import Queue
7
- from typing import Any, List, Mapping, Optional
7
+ from typing import Any, List, Literal
8
8
 
9
9
  import grpc
10
10
 
11
- from hatchet_sdk.clients.dispatcher.action_listener import Action
12
- from hatchet_sdk.clients.dispatcher.dispatcher import (
11
+ from hatchet_sdk.clients.dispatcher.action_listener import (
12
+ Action,
13
13
  ActionListener,
14
+ ActionType,
14
15
  GetActionListenerRequest,
15
- new_dispatcher,
16
16
  )
17
+ from hatchet_sdk.clients.dispatcher.dispatcher import DispatcherClient
18
+ from hatchet_sdk.config import ClientConfig
17
19
  from hatchet_sdk.contracts.dispatcher_pb2 import (
18
20
  GROUP_KEY_EVENT_TYPE_STARTED,
19
21
  STEP_EVENT_TYPE_STARTED,
20
- ActionType,
21
22
  )
22
- from hatchet_sdk.loader import ClientConfig
23
23
  from hatchet_sdk.logger import logger
24
24
  from hatchet_sdk.utils.backoff import exp_backoff_sleep
25
25
 
@@ -30,10 +30,11 @@ ACTION_EVENT_RETRY_COUNT = 5
30
30
  class ActionEvent:
31
31
  action: Action
32
32
  type: Any # TODO type
33
- payload: Optional[str] = None
33
+ payload: str
34
34
 
35
35
 
36
- STOP_LOOP = "STOP_LOOP" # Sentinel object to stop the loop
36
+ STOP_LOOP_TYPE = Literal["STOP_LOOP"]
37
+ STOP_LOOP: STOP_LOOP_TYPE = "STOP_LOOP" # Sentinel object to stop the loop
37
38
 
38
39
  # TODO link to a block post
39
40
  BLOCKED_THREAD_WARNING = (
@@ -41,7 +42,7 @@ BLOCKED_THREAD_WARNING = (
41
42
  )
42
43
 
43
44
 
44
- def noop_handler():
45
+ def noop_handler() -> None:
45
46
  pass
46
47
 
47
48
 
@@ -51,22 +52,22 @@ class WorkerActionListenerProcess:
51
52
  actions: List[str]
52
53
  max_runs: int
53
54
  config: ClientConfig
54
- action_queue: Queue
55
- event_queue: Queue
55
+ action_queue: "Queue[Action]"
56
+ event_queue: "Queue[ActionEvent | STOP_LOOP_TYPE]"
56
57
  handle_kill: bool = True
57
58
  debug: bool = False
58
- labels: dict = field(default_factory=dict)
59
+ labels: dict[str, str | int] = field(default_factory=dict)
59
60
 
60
- listener: ActionListener = field(init=False, default=None)
61
+ listener: ActionListener = field(init=False)
61
62
 
62
63
  killing: bool = field(init=False, default=False)
63
64
 
64
- action_loop_task: asyncio.Task = field(init=False, default=None)
65
- event_send_loop_task: asyncio.Task = field(init=False, default=None)
65
+ action_loop_task: asyncio.Task[None] | None = field(init=False, default=None)
66
+ event_send_loop_task: asyncio.Task[None] | None = field(init=False, default=None)
66
67
 
67
- running_step_runs: Mapping[str, float] = field(init=False, default_factory=dict)
68
+ running_step_runs: dict[str, float] = field(init=False, default_factory=dict)
68
69
 
69
- def __post_init__(self):
70
+ def __post_init__(self) -> None:
70
71
  if self.debug:
71
72
  logger.setLevel(logging.DEBUG)
72
73
 
@@ -77,7 +78,7 @@ class WorkerActionListenerProcess:
77
78
  signal.SIGQUIT, lambda: asyncio.create_task(self.exit_gracefully())
78
79
  )
79
80
 
80
- async def start(self, retry_attempt=0):
81
+ async def start(self, retry_attempt: int = 0) -> None:
81
82
  if retry_attempt > 5:
82
83
  logger.error("could not start action listener")
83
84
  return
@@ -85,7 +86,7 @@ class WorkerActionListenerProcess:
85
86
  logger.debug(f"starting action listener: {self.name}")
86
87
 
87
88
  try:
88
- self.dispatcher_client = new_dispatcher(self.config)
89
+ self.dispatcher_client = DispatcherClient(self.config)
89
90
 
90
91
  self.listener = await self.dispatcher_client.get_action_listener(
91
92
  GetActionListenerRequest(
@@ -108,13 +109,13 @@ class WorkerActionListenerProcess:
108
109
  self.blocked_main_loop = asyncio.create_task(self.start_blocked_main_loop())
109
110
 
110
111
  # TODO move event methods to separate class
111
- async def _get_event(self):
112
+ async def _get_event(self) -> ActionEvent | STOP_LOOP_TYPE:
112
113
  loop = asyncio.get_running_loop()
113
114
  return await loop.run_in_executor(None, self.event_queue.get)
114
115
 
115
- async def start_event_send_loop(self):
116
+ async def start_event_send_loop(self) -> None:
116
117
  while True:
117
- event: ActionEvent = await self._get_event()
118
+ event = await self._get_event()
118
119
  if event == STOP_LOOP:
119
120
  logger.debug("stopping event send loop...")
120
121
  break
@@ -122,11 +123,11 @@ class WorkerActionListenerProcess:
122
123
  logger.debug(f"tx: event: {event.action.action_id}/{event.type}")
123
124
  asyncio.create_task(self.send_event(event))
124
125
 
125
- async def start_blocked_main_loop(self):
126
+ async def start_blocked_main_loop(self) -> None:
126
127
  threshold = 1
127
128
  while not self.killing:
128
129
  count = 0
129
- for step_run_id, start_time in self.running_step_runs.items():
130
+ for _, start_time in self.running_step_runs.items():
130
131
  diff = self.now() - start_time
131
132
  if diff > threshold:
132
133
  count += 1
@@ -135,7 +136,7 @@ class WorkerActionListenerProcess:
135
136
  logger.warning(f"{BLOCKED_THREAD_WARNING}: Waiting Steps {count}")
136
137
  await asyncio.sleep(1)
137
138
 
138
- async def send_event(self, event: ActionEvent, retry_attempt: int = 1):
139
+ async def send_event(self, event: ActionEvent, retry_attempt: int = 1) -> None:
139
140
  try:
140
141
  match event.action.action_type:
141
142
  # FIXME: all events sent from an execution of a function are of type ActionType.START_STEP_RUN since
@@ -185,10 +186,10 @@ class WorkerActionListenerProcess:
185
186
  await exp_backoff_sleep(retry_attempt, 1)
186
187
  await self.send_event(event, retry_attempt + 1)
187
188
 
188
- def now(self):
189
+ def now(self) -> float:
189
190
  return time.time()
190
191
 
191
- async def start_action_loop(self):
192
+ async def start_action_loop(self) -> None:
192
193
  try:
193
194
  async for action in self.listener:
194
195
  if action is None:
@@ -201,6 +202,7 @@ class WorkerActionListenerProcess:
201
202
  ActionEvent(
202
203
  action=action,
203
204
  type=STEP_EVENT_TYPE_STARTED, # TODO ack type
205
+ payload="",
204
206
  )
205
207
  )
206
208
  logger.info(
@@ -220,6 +222,7 @@ class WorkerActionListenerProcess:
220
222
  ActionEvent(
221
223
  action=action,
222
224
  type=GROUP_KEY_EVENT_TYPE_STARTED, # TODO ack type
225
+ payload="",
223
226
  )
224
227
  )
225
228
  logger.info(
@@ -239,9 +242,9 @@ class WorkerActionListenerProcess:
239
242
  finally:
240
243
  logger.info("action loop closed")
241
244
  if not self.killing:
242
- await self.exit_gracefully(skip_unregister=True)
245
+ await self.exit_gracefully()
243
246
 
244
- async def cleanup(self):
247
+ async def cleanup(self) -> None:
245
248
  self.killing = True
246
249
 
247
250
  if self.listener is not None:
@@ -249,7 +252,7 @@ class WorkerActionListenerProcess:
249
252
 
250
253
  self.event_queue.put(STOP_LOOP)
251
254
 
252
- async def exit_gracefully(self, skip_unregister=False):
255
+ async def exit_gracefully(self) -> None:
253
256
  if self.killing:
254
257
  return
255
258
 
@@ -262,13 +265,13 @@ class WorkerActionListenerProcess:
262
265
 
263
266
  logger.info("action listener closed")
264
267
 
265
- def exit_forcefully(self):
268
+ def exit_forcefully(self) -> None:
266
269
  asyncio.run(self.cleanup())
267
270
  logger.debug("forcefully closing listener...")
268
271
 
269
272
 
270
- def worker_action_listener_process(*args, **kwargs):
271
- async def run():
273
+ def worker_action_listener_process(*args: Any, **kwargs: Any) -> None:
274
+ async def run() -> None:
272
275
  process = WorkerActionListenerProcess(*args, **kwargs)
273
276
  await process.start()
274
277
  # Keep the process running
@@ -2,18 +2,20 @@ import asyncio
2
2
  import logging
3
3
  from dataclasses import dataclass, field
4
4
  from multiprocessing import Queue
5
- from typing import Callable, TypeVar
5
+ from typing import Any, Literal, TypeVar
6
6
 
7
- from hatchet_sdk import Context
8
7
  from hatchet_sdk.client import Client, new_client_raw
9
8
  from hatchet_sdk.clients.dispatcher.action_listener import Action
10
- from hatchet_sdk.loader import ClientConfig
9
+ from hatchet_sdk.config import ClientConfig
11
10
  from hatchet_sdk.logger import logger
12
- from hatchet_sdk.utils.types import WorkflowValidator
11
+ from hatchet_sdk.utils.typing import WorkflowValidator
12
+ from hatchet_sdk.worker.action_listener_process import ActionEvent
13
13
  from hatchet_sdk.worker.runner.runner import Runner
14
14
  from hatchet_sdk.worker.runner.utils.capture_logs import capture_logs
15
+ from hatchet_sdk.workflow import Step
15
16
 
16
- STOP_LOOP = "STOP_LOOP"
17
+ STOP_LOOP_TYPE = Literal["STOP_LOOP"]
18
+ STOP_LOOP: STOP_LOOP_TYPE = "STOP_LOOP"
17
19
 
18
20
  T = TypeVar("T")
19
21
 
@@ -21,32 +23,32 @@ T = TypeVar("T")
21
23
  @dataclass
22
24
  class WorkerActionRunLoopManager:
23
25
  name: str
24
- action_registry: dict[str, Callable[[Context], T]]
26
+ action_registry: dict[str, Step[Any]]
25
27
  validator_registry: dict[str, WorkflowValidator]
26
28
  max_runs: int | None
27
29
  config: ClientConfig
28
- action_queue: Queue
29
- event_queue: Queue
30
+ action_queue: "Queue[Action | STOP_LOOP_TYPE]"
31
+ event_queue: "Queue[ActionEvent]"
30
32
  loop: asyncio.AbstractEventLoop
31
33
  handle_kill: bool = True
32
34
  debug: bool = False
33
35
  labels: dict[str, str | int] = field(default_factory=dict)
34
36
 
35
- client: Client = field(init=False, default=None)
37
+ client: Client = field(init=False)
36
38
 
37
39
  killing: bool = field(init=False, default=False)
38
- runner: Runner = field(init=False, default=None)
40
+ runner: Runner | None = field(init=False, default=None)
39
41
 
40
- def __post_init__(self):
42
+ def __post_init__(self) -> None:
41
43
  if self.debug:
42
44
  logger.setLevel(logging.DEBUG)
43
45
  self.client = new_client_raw(self.config, self.debug)
44
46
  self.start()
45
47
 
46
- def start(self, retry_count=1):
47
- k = self.loop.create_task(self.async_start(retry_count))
48
+ def start(self, retry_count: int = 1) -> None:
49
+ k = self.loop.create_task(self.aio_start(retry_count)) # noqa: F841
48
50
 
49
- async def async_start(self, retry_count=1):
51
+ async def aio_start(self, retry_count: int = 1) -> None:
50
52
  await capture_logs(
51
53
  self.client.logInterceptor,
52
54
  self.client.event,
@@ -83,7 +85,7 @@ class WorkerActionRunLoopManager:
83
85
 
84
86
  logger.debug(f"'{self.name}' waiting for {list(self.action_registry.keys())}")
85
87
  while not self.killing:
86
- action: Action = await self._get_action()
88
+ action = await self._get_action()
87
89
  if action == STOP_LOOP:
88
90
  logger.debug("stopping action runner loop...")
89
91
  break
@@ -91,7 +93,7 @@ class WorkerActionRunLoopManager:
91
93
  self.runner.run(action)
92
94
  logger.debug("action runner loop stopped")
93
95
 
94
- async def _get_action(self):
96
+ async def _get_action(self) -> Action | STOP_LOOP_TYPE:
95
97
  return await self.loop.run_in_executor(None, self.action_queue.get)
96
98
 
97
99
  async def exit_gracefully(self) -> None:
@@ -8,17 +8,18 @@ from concurrent.futures import ThreadPoolExecutor
8
8
  from enum import Enum
9
9
  from multiprocessing import Queue
10
10
  from threading import Thread, current_thread
11
- from typing import Any, Callable, Dict, Literal, Type, TypeVar, cast, overload
11
+ from typing import Any, Callable, Dict, TypeVar, cast
12
12
 
13
13
  from pydantic import BaseModel
14
14
 
15
15
  from hatchet_sdk.client import new_client_raw
16
- from hatchet_sdk.clients.admin import new_admin
17
- from hatchet_sdk.clients.dispatcher.action_listener import Action
18
- from hatchet_sdk.clients.dispatcher.dispatcher import new_dispatcher
19
- from hatchet_sdk.clients.run_event_listener import new_listener
16
+ from hatchet_sdk.clients.admin import AdminClient
17
+ from hatchet_sdk.clients.dispatcher.action_listener import Action, ActionType
18
+ from hatchet_sdk.clients.dispatcher.dispatcher import DispatcherClient
19
+ from hatchet_sdk.clients.run_event_listener import RunEventListenerClient
20
20
  from hatchet_sdk.clients.workflow_listener import PooledWorkflowRunListener
21
- from hatchet_sdk.context import Context # type: ignore[attr-defined]
21
+ from hatchet_sdk.config import ClientConfig
22
+ from hatchet_sdk.context.context import Context
22
23
  from hatchet_sdk.context.worker_context import WorkerContext
23
24
  from hatchet_sdk.contracts.dispatcher_pb2 import (
24
25
  GROUP_KEY_EVENT_TYPE_COMPLETED,
@@ -27,14 +28,14 @@ from hatchet_sdk.contracts.dispatcher_pb2 import (
27
28
  STEP_EVENT_TYPE_COMPLETED,
28
29
  STEP_EVENT_TYPE_FAILED,
29
30
  STEP_EVENT_TYPE_STARTED,
30
- ActionType,
31
31
  )
32
- from hatchet_sdk.loader import ClientConfig
33
32
  from hatchet_sdk.logger import logger
34
- from hatchet_sdk.utils.types import WorkflowValidator
35
- from hatchet_sdk.v2.callable import DurableContext
33
+ from hatchet_sdk.utils.typing import WorkflowValidator
36
34
  from hatchet_sdk.worker.action_listener_process import ActionEvent
37
35
  from hatchet_sdk.worker.runner.utils.capture_logs import copy_context_vars, sr, wr
36
+ from hatchet_sdk.workflow import Step
37
+
38
+ T = TypeVar("T")
38
39
 
39
40
 
40
41
  class WorkerStatus(Enum):
@@ -51,7 +52,7 @@ class Runner:
51
52
  event_queue: "Queue[Any]",
52
53
  max_runs: int | None = None,
53
54
  handle_kill: bool = True,
54
- action_registry: dict[str, Callable[..., Any]] = {},
55
+ action_registry: dict[str, Step[T]] = {},
55
56
  validator_registry: dict[str, WorkflowValidator] = {},
56
57
  config: ClientConfig = ClientConfig(),
57
58
  labels: dict[str, str | int] = {},
@@ -63,7 +64,7 @@ class Runner:
63
64
  self.max_runs = max_runs
64
65
  self.tasks: dict[str, asyncio.Task[Any]] = {} # Store run ids and futures
65
66
  self.contexts: dict[str, Context] = {} # Store run ids and contexts
66
- self.action_registry: dict[str, Callable[..., Any]] = action_registry
67
+ self.action_registry: dict[str, Step[T]] = action_registry
67
68
  self.validator_registry = validator_registry
68
69
 
69
70
  self.event_queue = event_queue
@@ -77,9 +78,9 @@ class Runner:
77
78
 
78
79
  # We need to initialize a new admin and dispatcher client *after* we've started the event loop,
79
80
  # otherwise the grpc.aio methods will use a different event loop and we'll get a bunch of errors.
80
- self.dispatcher_client = new_dispatcher(self.config)
81
- self.admin_client = new_admin(self.config)
82
- self.workflow_run_event_listener = new_listener(self.config)
81
+ self.dispatcher_client = DispatcherClient(self.config)
82
+ self.admin_client = AdminClient(self.config)
83
+ self.workflow_run_event_listener = RunEventListenerClient(self.config)
83
84
  self.client.workflow_listener = PooledWorkflowRunListener(self.config)
84
85
 
85
86
  self.worker_context = WorkerContext(
@@ -194,10 +195,7 @@ class Runner:
194
195
 
195
196
  return inner_callback
196
197
 
197
- ## TODO: Stricter type hinting here
198
- def thread_action_func(
199
- self, context: Context, action_func: Callable[..., Any], action: Action
200
- ) -> Any:
198
+ def thread_action_func(self, context: Context, step: Step[T], action: Action) -> T:
201
199
  if action.step_run_id is not None and action.step_run_id != "":
202
200
  self.threads[action.step_run_id] = current_thread()
203
201
  elif (
@@ -206,25 +204,22 @@ class Runner:
206
204
  ):
207
205
  self.threads[action.get_group_key_run_id] = current_thread()
208
206
 
209
- return action_func(context)
207
+ return step.call(context)
210
208
 
211
- ## TODO: Stricter type hinting here
212
209
  # We wrap all actions in an async func
213
210
  async def async_wrapped_action_func(
214
211
  self,
215
212
  context: Context,
216
- action_func: Callable[..., Any],
213
+ step: Step[T],
217
214
  action: Action,
218
215
  run_id: str,
219
- ) -> Any:
220
- wr.set(context.workflow_run_id())
216
+ ) -> T:
217
+ wr.set(context.workflow_run_id)
221
218
  sr.set(context.step_run_id)
222
219
 
223
220
  try:
224
- if (
225
- hasattr(action_func, "is_coroutine") and action_func.is_coroutine
226
- ) or asyncio.iscoroutinefunction(action_func):
227
- return await action_func(context)
221
+ if step.is_async_function:
222
+ return await step.aio_call(context)
228
223
  else:
229
224
  pfunc = functools.partial(
230
225
  # we must copy the context vars to the new thread, as only asyncio natively supports
@@ -233,7 +228,7 @@ class Runner:
233
228
  contextvars.copy_context().items(),
234
229
  self.thread_action_func,
235
230
  context,
236
- action_func,
231
+ step,
237
232
  action,
238
233
  )
239
234
 
@@ -260,23 +255,7 @@ class Runner:
260
255
  if run_id in self.contexts:
261
256
  del self.contexts[run_id]
262
257
 
263
- def create_context(
264
- self, action: Action, action_func: Callable[..., Any] | None
265
- ) -> Context | DurableContext:
266
- if hasattr(action_func, "durable") and getattr(action_func, "durable"):
267
- return DurableContext(
268
- action,
269
- self.dispatcher_client,
270
- self.admin_client,
271
- self.client.event,
272
- self.client.rest,
273
- self.client.workflow_listener,
274
- self.workflow_run_event_listener,
275
- self.worker_context,
276
- self.client.config.namespace,
277
- validator_registry=self.validator_registry,
278
- )
279
-
258
+ def create_context(self, action: Action) -> Context:
280
259
  return Context(
281
260
  action,
282
261
  self.dispatcher_client,
@@ -291,22 +270,19 @@ class Runner:
291
270
  )
292
271
 
293
272
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
294
- async def handle_start_step_run(self, action: Action) -> None | Exception:
273
+ async def handle_start_step_run(self, action: Action) -> None:
295
274
  action_name = action.action_id
296
275
 
297
276
  # Find the corresponding action function from the registry
298
277
  action_func = self.action_registry.get(action_name)
299
278
 
300
- context = self.create_context(action, action_func)
279
+ context = self.create_context(action)
301
280
 
302
281
  self.contexts[action.step_run_id] = context
303
282
 
304
283
  if action_func:
305
284
  self.event_queue.put(
306
- ActionEvent(
307
- action=action,
308
- type=STEP_EVENT_TYPE_STARTED,
309
- )
285
+ ActionEvent(action=action, type=STEP_EVENT_TYPE_STARTED, payload="")
310
286
  )
311
287
 
312
288
  loop = asyncio.get_event_loop()
@@ -321,10 +297,9 @@ class Runner:
321
297
 
322
298
  try:
323
299
  await task
324
- except Exception as e:
325
- return e
326
-
327
- return None
300
+ except Exception:
301
+ # do nothing, this should be caught in the callback
302
+ pass
328
303
 
329
304
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
330
305
  async def handle_start_group_key_run(self, action: Action) -> Exception | None:
@@ -350,8 +325,7 @@ class Runner:
350
325
  # send an event that the group key run has started
351
326
  self.event_queue.put(
352
327
  ActionEvent(
353
- action=action,
354
- type=GROUP_KEY_EVENT_TYPE_STARTED,
328
+ action=action, type=GROUP_KEY_EVENT_TYPE_STARTED, payload=""
355
329
  )
356
330
  )
357
331
 
@@ -421,6 +395,11 @@ class Runner:
421
395
 
422
396
  # check if thread is still running, if so, print a warning
423
397
  if run_id in self.threads:
398
+ thread = self.threads.get(run_id)
399
+ if thread and self.client.config.enable_force_kill_sync_threads:
400
+ self.force_kill_thread(thread)
401
+ await asyncio.sleep(1)
402
+
424
403
  logger.warning(
425
404
  f"Thread {self.threads[run_id].ident} with run id {run_id} is still running after cancellation. This could cause the thread pool to get blocked and prevent new tasks from running."
426
405
  )
@@ -428,7 +407,6 @@ class Runner:
428
407
  self.cleanup_run_id(run_id)
429
408
 
430
409
  def serialize_output(self, output: Any) -> str:
431
-
432
410
  if isinstance(output, BaseModel):
433
411
  return output.model_dump_json()
434
412
 
@@ -2,11 +2,12 @@ import contextvars
2
2
  import functools
3
3
  import logging
4
4
  from concurrent.futures import ThreadPoolExecutor
5
+ from contextvars import ContextVar
5
6
  from io import StringIO
6
- from typing import Any, Coroutine
7
+ from typing import Any, Awaitable, Callable, ItemsView, ParamSpec, TypeVar
7
8
 
8
- from hatchet_sdk import logger
9
9
  from hatchet_sdk.clients.events import EventClient
10
+ from hatchet_sdk.logger import logger
10
11
 
11
12
  wr: contextvars.ContextVar[str | None] = contextvars.ContextVar(
12
13
  "workflow_run_id", default=None
@@ -16,7 +17,16 @@ sr: contextvars.ContextVar[str | None] = contextvars.ContextVar(
16
17
  )
17
18
 
18
19
 
19
- def copy_context_vars(ctx_vars, func, *args, **kwargs):
20
+ T = TypeVar("T")
21
+ P = ParamSpec("P")
22
+
23
+
24
+ def copy_context_vars(
25
+ ctx_vars: ItemsView[ContextVar[Any], Any],
26
+ func: Callable[P, T],
27
+ *args: P.args,
28
+ **kwargs: P.kwargs,
29
+ ) -> T:
20
30
  for var, value in ctx_vars:
21
31
  var.set(value)
22
32
  return func(*args, **kwargs)
@@ -25,19 +35,20 @@ def copy_context_vars(ctx_vars, func, *args, **kwargs):
25
35
  class InjectingFilter(logging.Filter):
26
36
  # For some reason, only the InjectingFilter has access to the contextvars method sr.get(),
27
37
  # otherwise we would use emit within the CustomLogHandler
28
- def filter(self, record):
38
+ def filter(self, record: logging.LogRecord) -> bool:
39
+ ## TODO: Change how we do this to not assign to the log record
29
40
  record.workflow_run_id = wr.get()
30
41
  record.step_run_id = sr.get()
31
42
  return True
32
43
 
33
44
 
34
- class CustomLogHandler(logging.StreamHandler):
35
- def __init__(self, event_client: EventClient, stream=None):
45
+ class CustomLogHandler(logging.StreamHandler): # type: ignore[type-arg]
46
+ def __init__(self, event_client: EventClient, stream: StringIO | None = None):
36
47
  super().__init__(stream)
37
48
  self.logger_thread_pool = ThreadPoolExecutor(max_workers=1)
38
49
  self.event_client = event_client
39
50
 
40
- def _log(self, line: str, step_run_id: str | None):
51
+ def _log(self, line: str, step_run_id: str | None) -> None:
41
52
  try:
42
53
  if not step_run_id:
43
54
  return
@@ -46,20 +57,20 @@ class CustomLogHandler(logging.StreamHandler):
46
57
  except Exception as e:
47
58
  logger.error(f"Error logging: {e}")
48
59
 
49
- def emit(self, record):
60
+ def emit(self, record: logging.LogRecord) -> None:
50
61
  super().emit(record)
51
62
 
52
63
  log_entry = self.format(record)
53
- self.logger_thread_pool.submit(self._log, log_entry, record.step_run_id)
64
+
65
+ ## TODO: Change how we do this to not assign to the log record
66
+ self.logger_thread_pool.submit(self._log, log_entry, record.step_run_id) # type: ignore
54
67
 
55
68
 
56
69
  def capture_logs(
57
- logger: logging.Logger,
58
- event_client: EventClient,
59
- func: Coroutine[Any, Any, Any],
60
- ):
70
+ logger: logging.Logger, event_client: "EventClient", func: Callable[P, Awaitable[T]]
71
+ ) -> Callable[P, Awaitable[T]]:
61
72
  @functools.wraps(func)
62
- async def wrapper(*args, **kwargs):
73
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
63
74
  if not logger:
64
75
  raise Exception("No logger configured on client")
65
76
 
@@ -1,6 +1,6 @@
1
1
  import traceback
2
2
 
3
3
 
4
- def errorWithTraceback(message: str, e: Exception):
4
+ def errorWithTraceback(message: str, e: Exception) -> str:
5
5
  trace = "".join(traceback.format_exception(type(e), e, e.__traceback__))
6
6
  return f"{message}\n{trace}"