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
@@ -0,0 +1,327 @@
1
+ import asyncio
2
+ import json
3
+ from collections.abc import AsyncIterator
4
+ from typing import Any, Literal, cast
5
+
6
+ import grpc
7
+ import grpc.aio
8
+ from grpc._cython import cygrpc # type: ignore[attr-defined]
9
+ from pydantic import BaseModel, ConfigDict
10
+
11
+ from hatchet_sdk.clients.event_ts import ThreadSafeEvent, read_with_interrupt
12
+ from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
13
+ from hatchet_sdk.config import ClientConfig
14
+ from hatchet_sdk.connection import new_conn
15
+ from hatchet_sdk.contracts.v1.dispatcher_pb2 import (
16
+ DurableEvent,
17
+ ListenForDurableEventRequest,
18
+ )
19
+ from hatchet_sdk.contracts.v1.dispatcher_pb2 import (
20
+ RegisterDurableEventRequest as RegisterDurableEventRequestProto,
21
+ )
22
+ from hatchet_sdk.contracts.v1.dispatcher_pb2_grpc import V1DispatcherStub
23
+ from hatchet_sdk.contracts.v1.shared.condition_pb2 import DurableEventListenerConditions
24
+ from hatchet_sdk.logger import logger
25
+ from hatchet_sdk.metadata import get_metadata
26
+ from hatchet_sdk.waits import SleepCondition, UserEventCondition
27
+
28
+ DEFAULT_DURABLE_EVENT_LISTENER_RETRY_INTERVAL = 3 # seconds
29
+ DEFAULT_DURABLE_EVENT_LISTENER_RETRY_COUNT = 5
30
+ DEFAULT_DURABLE_EVENT_LISTENER_INTERRUPT_INTERVAL = 1800 # 30 minutes
31
+
32
+
33
+ class _Subscription:
34
+ def __init__(self, id: int, task_id: str, signal_key: str):
35
+ self.id = id
36
+ self.task_id = task_id
37
+ self.signal_key = signal_key
38
+ self.queue: asyncio.Queue[DurableEvent | None] = asyncio.Queue()
39
+
40
+ async def __aiter__(self) -> "_Subscription":
41
+ return self
42
+
43
+ async def __anext__(self) -> DurableEvent | None:
44
+ return await self.queue.get()
45
+
46
+ async def get(self) -> DurableEvent:
47
+ event = await self.queue.get()
48
+
49
+ if event is None:
50
+ raise StopAsyncIteration
51
+
52
+ return event
53
+
54
+ async def put(self, item: DurableEvent) -> None:
55
+ await self.queue.put(item)
56
+
57
+ async def close(self) -> None:
58
+ await self.queue.put(None)
59
+
60
+
61
+ class RegisterDurableEventRequest(BaseModel):
62
+ model_config = ConfigDict(arbitrary_types_allowed=True)
63
+
64
+ task_id: str
65
+ signal_key: str
66
+ conditions: list[SleepCondition | UserEventCondition]
67
+
68
+ def to_proto(self) -> RegisterDurableEventRequestProto:
69
+ return RegisterDurableEventRequestProto(
70
+ task_id=self.task_id,
71
+ signal_key=self.signal_key,
72
+ conditions=DurableEventListenerConditions(
73
+ sleep_conditions=[
74
+ c.to_pb() for c in self.conditions if isinstance(c, SleepCondition)
75
+ ],
76
+ user_event_conditions=[
77
+ c.to_pb()
78
+ for c in self.conditions
79
+ if isinstance(c, UserEventCondition)
80
+ ],
81
+ ),
82
+ )
83
+
84
+
85
+ class DurableEventListener:
86
+ def __init__(self, config: ClientConfig):
87
+ try:
88
+ asyncio.get_running_loop()
89
+ except RuntimeError:
90
+ loop = asyncio.new_event_loop()
91
+ asyncio.set_event_loop(loop)
92
+
93
+ conn = new_conn(config, True)
94
+ self.client = V1DispatcherStub(conn) # type: ignore[no-untyped-call]
95
+ self.token = config.token
96
+ self.config = config
97
+
98
+ # list of all active subscriptions, mapping from a subscription id to a task id and signal key
99
+ self.subscriptions_to_task_id_signal_key: dict[int, tuple[str, str]] = {}
100
+
101
+ # task id-signal key tuples mapped to an array of subscription ids
102
+ self.task_id_signal_key_to_subscriptions: dict[tuple[str, str], list[int]] = {}
103
+
104
+ self.subscription_counter: int = 0
105
+ self.subscription_counter_lock: asyncio.Lock = asyncio.Lock()
106
+
107
+ self.requests: asyncio.Queue[ListenForDurableEventRequest | int] = (
108
+ asyncio.Queue()
109
+ )
110
+
111
+ self.listener: (
112
+ grpc.aio.UnaryStreamCall[ListenForDurableEventRequest, DurableEvent] | None
113
+ ) = None
114
+ self.listener_task: asyncio.Task[None] | None = None
115
+
116
+ self.curr_requester: int = 0
117
+
118
+ self.events: dict[int, _Subscription] = {}
119
+
120
+ self.interrupter: asyncio.Task[None] | None = None
121
+
122
+ async def _interrupter(self) -> None:
123
+ """
124
+ _interrupter runs in a separate thread and interrupts the listener according to a configurable duration.
125
+ """
126
+ await asyncio.sleep(DEFAULT_DURABLE_EVENT_LISTENER_INTERRUPT_INTERVAL)
127
+
128
+ if self.interrupt is not None:
129
+ self.interrupt.set()
130
+
131
+ async def _init_producer(self) -> None:
132
+ try:
133
+ if not self.listener:
134
+ while True:
135
+ try:
136
+ self.listener = await self._retry_subscribe()
137
+
138
+ logger.debug("Workflow run listener connected.")
139
+
140
+ # spawn an interrupter task
141
+ if self.interrupter is not None and not self.interrupter.done():
142
+ self.interrupter.cancel()
143
+
144
+ self.interrupter = asyncio.create_task(self._interrupter())
145
+
146
+ while True:
147
+ self.interrupt = ThreadSafeEvent()
148
+ if self.listener is None:
149
+ continue
150
+
151
+ t = asyncio.create_task(
152
+ read_with_interrupt(self.listener, self.interrupt)
153
+ )
154
+ await self.interrupt.wait()
155
+
156
+ if not t.done():
157
+ logger.warning(
158
+ "Interrupted read_with_interrupt task of durable event listener"
159
+ )
160
+
161
+ t.cancel()
162
+ if self.listener:
163
+ self.listener.cancel()
164
+ await asyncio.sleep(
165
+ DEFAULT_DURABLE_EVENT_LISTENER_RETRY_INTERVAL
166
+ )
167
+ break
168
+
169
+ event = t.result()
170
+
171
+ if event is cygrpc.EOF:
172
+ break
173
+
174
+ # get a list of subscriptions for this task-signal pair
175
+ subscriptions = (
176
+ self.task_id_signal_key_to_subscriptions.get(
177
+ (event.task_id, event.signal_key), []
178
+ )
179
+ )
180
+
181
+ for subscription_id in subscriptions:
182
+ await self.events[subscription_id].put(event)
183
+
184
+ except grpc.RpcError as e:
185
+ logger.debug(f"grpc error in durable event listener: {e}")
186
+ await asyncio.sleep(
187
+ DEFAULT_DURABLE_EVENT_LISTENER_RETRY_INTERVAL
188
+ )
189
+ continue
190
+
191
+ except Exception as e:
192
+ logger.error(f"Error in durable event listener: {e}")
193
+
194
+ self.listener = None
195
+
196
+ # close all subscriptions
197
+ for subscription_id in self.events:
198
+ await self.events[subscription_id].close()
199
+
200
+ raise e
201
+
202
+ async def _request(self) -> AsyncIterator[ListenForDurableEventRequest]:
203
+ self.curr_requester = self.curr_requester + 1
204
+
205
+ # replay all existing subscriptions
206
+ for task_id, signal_key in set(
207
+ self.subscriptions_to_task_id_signal_key.values()
208
+ ):
209
+ yield ListenForDurableEventRequest(
210
+ task_id=task_id,
211
+ signal_key=signal_key,
212
+ )
213
+
214
+ while True:
215
+ request = await self.requests.get()
216
+
217
+ # if the request is an int which matches the current requester, then we should stop
218
+ if request == self.curr_requester:
219
+ break
220
+
221
+ # if we've gotten an int that doesn't match the current requester, then we should ignore it
222
+ if isinstance(request, int):
223
+ continue
224
+
225
+ yield request
226
+ self.requests.task_done()
227
+
228
+ def cleanup_subscription(self, subscription_id: int) -> None:
229
+ task_id_signal_key = self.subscriptions_to_task_id_signal_key[subscription_id]
230
+
231
+ if task_id_signal_key in self.task_id_signal_key_to_subscriptions:
232
+ self.task_id_signal_key_to_subscriptions[task_id_signal_key].remove(
233
+ subscription_id
234
+ )
235
+
236
+ del self.subscriptions_to_task_id_signal_key[subscription_id]
237
+ del self.events[subscription_id]
238
+
239
+ async def subscribe(self, task_id: str, signal_key: str) -> DurableEvent:
240
+ try:
241
+ # create a new subscription id, place a mutex on the counter
242
+ async with self.subscription_counter_lock:
243
+ self.subscription_counter += 1
244
+ subscription_id = self.subscription_counter
245
+
246
+ self.subscriptions_to_task_id_signal_key[subscription_id] = (
247
+ task_id,
248
+ signal_key,
249
+ )
250
+
251
+ if (task_id, signal_key) not in self.task_id_signal_key_to_subscriptions:
252
+ self.task_id_signal_key_to_subscriptions[(task_id, signal_key)] = [
253
+ subscription_id
254
+ ]
255
+ else:
256
+ self.task_id_signal_key_to_subscriptions[(task_id, signal_key)].append(
257
+ subscription_id
258
+ )
259
+
260
+ self.events[subscription_id] = _Subscription(
261
+ subscription_id, task_id, signal_key
262
+ )
263
+
264
+ await self.requests.put(
265
+ ListenForDurableEventRequest(
266
+ task_id=task_id,
267
+ signal_key=signal_key,
268
+ )
269
+ )
270
+
271
+ if not self.listener_task or self.listener_task.done():
272
+ self.listener_task = asyncio.create_task(self._init_producer())
273
+
274
+ return await self.events[subscription_id].get()
275
+ except asyncio.CancelledError:
276
+ raise
277
+ finally:
278
+ self.cleanup_subscription(subscription_id)
279
+
280
+ async def _retry_subscribe(
281
+ self,
282
+ ) -> grpc.aio.UnaryStreamCall[ListenForDurableEventRequest, DurableEvent]:
283
+ retries = 0
284
+
285
+ while retries < DEFAULT_DURABLE_EVENT_LISTENER_RETRY_COUNT:
286
+ try:
287
+ if retries > 0:
288
+ await asyncio.sleep(DEFAULT_DURABLE_EVENT_LISTENER_RETRY_INTERVAL)
289
+
290
+ # signal previous async iterator to stop
291
+ if self.curr_requester != 0:
292
+ self.requests.put_nowait(self.curr_requester)
293
+
294
+ return cast(
295
+ grpc.aio.UnaryStreamCall[
296
+ ListenForDurableEventRequest, DurableEvent
297
+ ],
298
+ self.client.ListenForDurableEvent(
299
+ self._request(),
300
+ metadata=get_metadata(self.token),
301
+ ),
302
+ )
303
+ except grpc.RpcError as e:
304
+ if e.code() == grpc.StatusCode.UNAVAILABLE:
305
+ retries = retries + 1
306
+ else:
307
+ raise ValueError(f"gRPC error: {e}")
308
+
309
+ raise ValueError("Failed to connect to durable event listener")
310
+
311
+ @tenacity_retry
312
+ def register_durable_event(
313
+ self, request: RegisterDurableEventRequest
314
+ ) -> Literal[True]:
315
+ self.client.RegisterDurableEvent(
316
+ request.to_proto(),
317
+ timeout=5,
318
+ metadata=get_metadata(self.token),
319
+ )
320
+
321
+ return True
322
+
323
+ @tenacity_retry
324
+ async def result(self, task_id: str, signal_key: str) -> dict[str, Any]:
325
+ event = await self.subscribe(task_id, signal_key)
326
+
327
+ return cast(dict[str, Any], json.loads(event.data.decode("utf-8")))
@@ -1,28 +1,41 @@
1
1
  import asyncio
2
- from typing import Any
2
+ from typing import TypeVar, cast
3
3
 
4
+ import grpc.aio
5
+ from grpc._cython import cygrpc # type: ignore[attr-defined]
4
6
 
5
- class Event_ts(asyncio.Event):
7
+
8
+ class ThreadSafeEvent(asyncio.Event):
6
9
  """
7
- Event_ts is a subclass of asyncio.Event that allows for thread-safe setting and clearing of the event.
10
+ ThreadSafeEvent is a subclass of asyncio.Event that allows for thread-safe setting and clearing of the event.
8
11
  """
9
12
 
10
- def __init__(self, *args, **kwargs):
11
- super().__init__(*args, **kwargs)
12
- if self._loop is None:
13
+ def __init__(self) -> None:
14
+ super().__init__()
15
+ if self._loop is None: # type: ignore[has-type]
13
16
  self._loop = asyncio.get_event_loop()
14
17
 
15
- def set(self):
18
+ def set(self) -> None:
16
19
  if not self._loop.is_closed():
17
20
  self._loop.call_soon_threadsafe(super().set)
18
21
 
19
- def clear(self):
22
+ def clear(self) -> None:
20
23
  self._loop.call_soon_threadsafe(super().clear)
21
24
 
22
25
 
23
- async def read_with_interrupt(listener: Any, interrupt: Event_ts):
26
+ TRequest = TypeVar("TRequest")
27
+ TResponse = TypeVar("TResponse")
28
+
29
+
30
+ async def read_with_interrupt(
31
+ listener: grpc.aio.UnaryStreamCall[TRequest, TResponse], interrupt: ThreadSafeEvent
32
+ ) -> TResponse:
24
33
  try:
25
34
  result = await listener.read()
26
- return result
35
+
36
+ if result is cygrpc.EOF:
37
+ raise ValueError("Unexpected EOF")
38
+
39
+ return cast(TResponse, result)
27
40
  finally:
28
41
  interrupt.set()
@@ -1,13 +1,14 @@
1
1
  import asyncio
2
2
  import datetime
3
3
  import json
4
- from typing import Any, Dict, List, Optional, TypedDict
5
- from uuid import uuid4
4
+ from typing import List, cast
6
5
 
7
6
  import grpc
8
7
  from google.protobuf import timestamp_pb2
8
+ from pydantic import BaseModel, Field
9
9
 
10
10
  from hatchet_sdk.clients.rest.tenacity_utils import tenacity_retry
11
+ from hatchet_sdk.config import ClientConfig
11
12
  from hatchet_sdk.contracts.events_pb2 import (
12
13
  BulkPushEventRequest,
13
14
  Event,
@@ -16,20 +17,18 @@ from hatchet_sdk.contracts.events_pb2 import (
16
17
  PutStreamEventRequest,
17
18
  )
18
19
  from hatchet_sdk.contracts.events_pb2_grpc import EventsServiceStub
19
- from hatchet_sdk.utils.serialization import flatten
20
+ from hatchet_sdk.metadata import get_metadata
21
+ from hatchet_sdk.utils.typing import JSONSerializableMapping
20
22
 
21
- from ..loader import ClientConfig
22
- from ..metadata import get_metadata
23
23
 
24
-
25
- def new_event(conn, config: ClientConfig):
24
+ def new_event(conn: grpc.Channel, config: ClientConfig) -> "EventClient":
26
25
  return EventClient(
27
- client=EventsServiceStub(conn),
26
+ client=EventsServiceStub(conn), # type: ignore[no-untyped-call]
28
27
  config=config,
29
28
  )
30
29
 
31
30
 
32
- def proto_timestamp_now():
31
+ def proto_timestamp_now() -> timestamp_pb2.Timestamp:
33
32
  t = datetime.datetime.now().timestamp()
34
33
  seconds = int(t)
35
34
  nanos = int(t % 1 * 1e9)
@@ -37,19 +36,19 @@ def proto_timestamp_now():
37
36
  return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
38
37
 
39
38
 
40
- class PushEventOptions(TypedDict, total=False):
41
- additional_metadata: Dict[str, str] | None = None
39
+ class PushEventOptions(BaseModel):
40
+ additional_metadata: JSONSerializableMapping = Field(default_factory=dict)
42
41
  namespace: str | None = None
43
42
 
44
43
 
45
- class BulkPushEventOptions(TypedDict, total=False):
44
+ class BulkPushEventOptions(BaseModel):
46
45
  namespace: str | None = None
47
46
 
48
47
 
49
- class BulkPushEventWithMetadata(TypedDict, total=False):
48
+ class BulkPushEventWithMetadata(BaseModel):
50
49
  key: str
51
- payload: Any
52
- additional_metadata: Optional[Dict[str, Any]] # Optional metadata
50
+ payload: JSONSerializableMapping = Field(default_factory=dict)
51
+ additional_metadata: JSONSerializableMapping = Field(default_factory=dict)
53
52
 
54
53
 
55
54
  class EventClient:
@@ -58,126 +57,124 @@ class EventClient:
58
57
  self.token = config.token
59
58
  self.namespace = config.namespace
60
59
 
61
- async def async_push(
62
- self, event_key, payload, options: Optional[PushEventOptions] = None
60
+ async def aio_push(
61
+ self,
62
+ event_key: str,
63
+ payload: JSONSerializableMapping,
64
+ options: PushEventOptions = PushEventOptions(),
63
65
  ) -> Event:
64
66
  return await asyncio.to_thread(
65
67
  self.push, event_key=event_key, payload=payload, options=options
66
68
  )
67
69
 
68
- async def async_bulk_push(
70
+ async def aio_bulk_push(
69
71
  self,
70
- events: List[BulkPushEventWithMetadata],
71
- options: Optional[BulkPushEventOptions] = None,
72
+ events: list[BulkPushEventWithMetadata],
73
+ options: BulkPushEventOptions = BulkPushEventOptions(),
72
74
  ) -> List[Event]:
73
75
  return await asyncio.to_thread(self.bulk_push, events=events, options=options)
74
76
 
75
77
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
76
78
  @tenacity_retry
77
- def push(self, event_key, payload, options: PushEventOptions = None) -> Event:
78
- namespace = self.namespace
79
-
80
- if (
81
- options is not None
82
- and "namespace" in options
83
- and options["namespace"] is not None
84
- ):
85
- namespace = options.pop("namespace")
86
-
79
+ def push(
80
+ self,
81
+ event_key: str,
82
+ payload: JSONSerializableMapping,
83
+ options: PushEventOptions = PushEventOptions(),
84
+ ) -> Event:
85
+ namespace = options.namespace or self.namespace
87
86
  namespaced_event_key = namespace + event_key
88
87
 
89
88
  try:
90
- meta = dict() if options is None else options["additional_metadata"]
91
- meta_bytes = None if meta is None else json.dumps(meta).encode("utf-8")
89
+ meta = options.additional_metadata
90
+ meta_bytes = None if meta is None else json.dumps(meta)
92
91
  except Exception as e:
93
92
  raise ValueError(f"Error encoding meta: {e}")
94
93
 
95
94
  try:
96
- payload_bytes = json.dumps(payload).encode("utf-8")
97
- except json.UnicodeEncodeError as e:
95
+ payload_str = json.dumps(payload)
96
+ except (TypeError, ValueError) as e:
98
97
  raise ValueError(f"Error encoding payload: {e}")
99
98
 
100
99
  request = PushEventRequest(
101
100
  key=namespaced_event_key,
102
- payload=payload_bytes,
101
+ payload=payload_str,
103
102
  eventTimestamp=proto_timestamp_now(),
104
103
  additionalMetadata=meta_bytes,
105
104
  )
106
105
 
107
- return self.client.Push(request, metadata=get_metadata(self.token))
106
+ return cast(Event, self.client.Push(request, metadata=get_metadata(self.token)))
107
+
108
+ def _create_push_event_request(
109
+ self,
110
+ event: BulkPushEventWithMetadata,
111
+ namespace: str,
112
+ ) -> PushEventRequest:
113
+ event_key = namespace + event.key
114
+ payload = event.payload
115
+
116
+ meta = event.additional_metadata
117
+
118
+ try:
119
+ meta_str = json.dumps(meta)
120
+ except Exception as e:
121
+ raise ValueError(f"Error encoding meta: {e}")
122
+
123
+ try:
124
+ serialized_payload = json.dumps(payload)
125
+ except (TypeError, ValueError) as e:
126
+ raise ValueError(f"Error serializing payload: {e}")
127
+
128
+ return PushEventRequest(
129
+ key=event_key,
130
+ payload=serialized_payload,
131
+ eventTimestamp=proto_timestamp_now(),
132
+ additionalMetadata=meta_str,
133
+ )
108
134
 
109
135
  ## IMPORTANT: Keep this method's signature in sync with the wrapper in the OTel instrumentor
110
136
  @tenacity_retry
111
137
  def bulk_push(
112
138
  self,
113
139
  events: List[BulkPushEventWithMetadata],
114
- options: BulkPushEventOptions = None,
140
+ options: BulkPushEventOptions = BulkPushEventOptions(),
115
141
  ) -> List[Event]:
116
- namespace = self.namespace
117
-
118
- if (
119
- options is not None
120
- and "namespace" in options
121
- and options["namespace"] is not None
122
- ):
123
- namespace = options.pop("namespace")
124
-
125
- bulk_events = []
126
- for event in events:
127
- event_key = namespace + event["key"]
128
- payload = event["payload"]
129
-
130
- try:
131
- meta = event.get("additional_metadata", {})
132
- meta_bytes = json.dumps(meta).encode("utf-8") if meta else None
133
- except Exception as e:
134
- raise ValueError(f"Error encoding meta: {e}")
135
-
136
- try:
137
- payload_bytes = json.dumps(payload).encode("utf-8")
138
- except json.UnicodeEncodeError as e:
139
- raise ValueError(f"Error encoding payload: {e}")
140
-
141
- request = PushEventRequest(
142
- key=event_key,
143
- payload=payload_bytes,
144
- eventTimestamp=proto_timestamp_now(),
145
- additionalMetadata=meta_bytes,
146
- )
147
- bulk_events.append(request)
148
-
149
- bulk_request = BulkPushEventRequest(events=bulk_events)
142
+ namespace = options.namespace or self.namespace
143
+
144
+ bulk_request = BulkPushEventRequest(
145
+ events=[
146
+ self._create_push_event_request(event, namespace) for event in events
147
+ ]
148
+ )
150
149
 
151
150
  response = self.client.BulkPush(bulk_request, metadata=get_metadata(self.token))
152
151
 
153
- return response.events
152
+ return cast(
153
+ list[Event],
154
+ response.events,
155
+ )
154
156
 
155
- def log(self, message: str, step_run_id: str):
156
- try:
157
- request = PutLogRequest(
158
- stepRunId=step_run_id,
159
- createdAt=proto_timestamp_now(),
160
- message=message,
161
- )
157
+ def log(self, message: str, step_run_id: str) -> None:
158
+ request = PutLogRequest(
159
+ stepRunId=step_run_id,
160
+ createdAt=proto_timestamp_now(),
161
+ message=message,
162
+ )
162
163
 
163
- self.client.PutLog(request, metadata=get_metadata(self.token))
164
- except Exception as e:
165
- raise ValueError(f"Error logging: {e}")
164
+ self.client.PutLog(request, metadata=get_metadata(self.token))
166
165
 
167
- def stream(self, data: str | bytes, step_run_id: str):
168
- try:
169
- if isinstance(data, str):
170
- data_bytes = data.encode("utf-8")
171
- elif isinstance(data, bytes):
172
- data_bytes = data
173
- else:
174
- raise ValueError("Invalid data type. Expected str, bytes, or file.")
175
-
176
- request = PutStreamEventRequest(
177
- stepRunId=step_run_id,
178
- createdAt=proto_timestamp_now(),
179
- message=data_bytes,
180
- )
181
- self.client.PutStreamEvent(request, metadata=get_metadata(self.token))
182
- except Exception as e:
183
- raise ValueError(f"Error putting stream event: {e}")
166
+ def stream(self, data: str | bytes, step_run_id: str) -> None:
167
+ if isinstance(data, str):
168
+ data_bytes = data.encode("utf-8")
169
+ elif isinstance(data, bytes):
170
+ data_bytes = data
171
+ else:
172
+ raise ValueError("Invalid data type. Expected str, bytes, or file.")
173
+
174
+ request = PutStreamEventRequest(
175
+ stepRunId=step_run_id,
176
+ createdAt=proto_timestamp_now(),
177
+ message=data_bytes,
178
+ )
179
+
180
+ self.client.PutStreamEvent(request, metadata=get_metadata(self.token))