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
hatchet_sdk/workflow.py CHANGED
@@ -1,64 +1,77 @@
1
- import functools
1
+ import asyncio
2
+ from dataclasses import dataclass, field
3
+ from datetime import datetime
4
+ from enum import Enum
2
5
  from typing import (
6
+ TYPE_CHECKING,
3
7
  Any,
8
+ Awaitable,
4
9
  Callable,
5
- Protocol,
10
+ Generic,
11
+ ParamSpec,
6
12
  Type,
13
+ TypeGuard,
7
14
  TypeVar,
8
15
  Union,
9
16
  cast,
10
- get_type_hints,
11
- runtime_checkable,
12
17
  )
13
18
 
14
- from pydantic import BaseModel
19
+ from google.protobuf import timestamp_pb2
20
+ from pydantic import BaseModel, ConfigDict
15
21
 
16
- from hatchet_sdk import ConcurrencyLimitStrategy
22
+ from hatchet_sdk.clients.admin import (
23
+ ChildTriggerWorkflowOptions,
24
+ ChildWorkflowRunDict,
25
+ ScheduleTriggerWorkflowOptions,
26
+ )
27
+ from hatchet_sdk.context.context import Context
28
+ from hatchet_sdk.contracts.workflows_pb2 import (
29
+ ConcurrencyLimitStrategy as ConcurrencyLimitStrategyProto,
30
+ )
17
31
  from hatchet_sdk.contracts.workflows_pb2 import (
32
+ CreateStepRateLimit,
18
33
  CreateWorkflowJobOpts,
19
34
  CreateWorkflowStepOpts,
20
35
  CreateWorkflowVersionOpts,
21
- StickyStrategy,
36
+ DesiredWorkerLabels,
37
+ )
38
+ from hatchet_sdk.contracts.workflows_pb2 import StickyStrategy as StickyStrategyProto
39
+ from hatchet_sdk.contracts.workflows_pb2 import (
22
40
  WorkflowConcurrencyOpts,
23
41
  WorkflowKind,
42
+ WorkflowVersion,
24
43
  )
44
+ from hatchet_sdk.labels import DesiredWorkerLabel
25
45
  from hatchet_sdk.logger import logger
26
- from hatchet_sdk.utils.typing import is_basemodel_subclass
46
+ from hatchet_sdk.rate_limit import RateLimit
47
+ from hatchet_sdk.utils.proto_enums import convert_python_enum_to_proto, maybe_int_to_str
48
+ from hatchet_sdk.workflow_run import WorkflowRunRef
27
49
 
50
+ if TYPE_CHECKING:
51
+ from hatchet_sdk import Hatchet
28
52
 
29
- class WorkflowStepProtocol(Protocol):
30
- def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
53
+ R = TypeVar("R")
54
+ P = ParamSpec("P")
31
55
 
32
- __name__: str
33
56
 
34
- _step_name: str
35
- _step_timeout: str | None
36
- _step_parents: list[str]
37
- _step_retries: int | None
38
- _step_rate_limits: list[str] | None
39
- _step_desired_worker_labels: dict[str, str]
40
- _step_backoff_factor: float | None
41
- _step_backoff_max_seconds: int | None
57
+ class EmptyModel(BaseModel):
58
+ model_config = ConfigDict(extra="allow")
42
59
 
43
- _concurrency_fn_name: str
44
- _concurrency_max_runs: int | None
45
- _concurrency_limit_strategy: str | None
46
60
 
47
- _on_failure_step_name: str
48
- _on_failure_step_timeout: str | None
49
- _on_failure_step_retries: int
50
- _on_failure_step_rate_limits: list[str] | None
51
- _on_failure_step_backoff_factor: float | None
52
- _on_failure_step_backoff_max_seconds: int | None
61
+ class StickyStrategy(str, Enum):
62
+ SOFT = "SOFT"
63
+ HARD = "HARD"
53
64
 
54
65
 
55
- StepsType = list[tuple[str, WorkflowStepProtocol]]
66
+ class ConcurrencyLimitStrategy(str, Enum):
67
+ CANCEL_IN_PROGRESS = "CANCEL_IN_PROGRESS"
68
+ DROP_NEWEST = "DROP_NEWEST"
69
+ QUEUE_NEWEST = "QUEUE_NEWEST"
70
+ GROUP_ROUND_ROBIN = "GROUP_ROUND_ROBIN"
71
+ CANCEL_NEWEST = "CANCEL_NEWEST"
56
72
 
57
- T = TypeVar("T")
58
- TW = TypeVar("TW", bound="WorkflowInterface")
59
73
 
60
-
61
- class ConcurrencyExpression:
74
+ class ConcurrencyExpression(BaseModel):
62
75
  """
63
76
  Defines concurrency limits for a workflow using a CEL expression.
64
77
 
@@ -71,191 +84,444 @@ class ConcurrencyExpression:
71
84
  ConcurrencyExpression("input.user_id", 5, ConcurrencyLimitStrategy.CANCEL_IN_PROGRESS)
72
85
  """
73
86
 
87
+ expression: str
88
+ max_runs: int
89
+ limit_strategy: ConcurrencyLimitStrategy
90
+
91
+
92
+ TWorkflowInput = TypeVar("TWorkflowInput", bound=BaseModel)
93
+
94
+
95
+ class WorkflowConfig(BaseModel):
96
+ model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
97
+
98
+ name: str = ""
99
+ on_events: list[str] = []
100
+ on_crons: list[str] = []
101
+ version: str = ""
102
+ timeout: str = "60m"
103
+ schedule_timeout: str = "5m"
104
+ sticky: StickyStrategy | None = None
105
+ default_priority: int = 1
106
+ concurrency: ConcurrencyExpression | None = None
107
+ input_validator: Type[BaseModel] = EmptyModel
108
+
109
+
110
+ class StepType(str, Enum):
111
+ DEFAULT = "default"
112
+ CONCURRENCY = "concurrency"
113
+ ON_FAILURE = "on_failure"
114
+
115
+
116
+ AsyncFunc = Callable[[Any, Context], Awaitable[R]]
117
+ SyncFunc = Callable[[Any, Context], R]
118
+ StepFunc = Union[AsyncFunc[R], SyncFunc[R]]
119
+
120
+
121
+ def is_async_fn(fn: StepFunc[R]) -> TypeGuard[AsyncFunc[R]]:
122
+ return asyncio.iscoroutinefunction(fn)
123
+
124
+
125
+ def is_sync_fn(fn: StepFunc[R]) -> TypeGuard[SyncFunc[R]]:
126
+ return not asyncio.iscoroutinefunction(fn)
127
+
128
+
129
+ class Step(Generic[R]):
74
130
  def __init__(
75
- self, expression: str, max_runs: int, limit_strategy: ConcurrencyLimitStrategy
76
- ):
77
- self.expression = expression
78
- self.max_runs = max_runs
79
- self.limit_strategy = limit_strategy
80
-
81
-
82
- @runtime_checkable
83
- class WorkflowInterface(Protocol):
84
- def get_name(self, namespace: str) -> str: ...
85
-
86
- def get_actions(self, namespace: str) -> list[tuple[str, Callable[..., Any]]]: ...
87
-
88
- def get_create_opts(self, namespace: str) -> Any: ...
89
-
90
- on_events: list[str] | None
91
- on_crons: list[str] | None
92
- name: str
93
- version: str
94
- timeout: str
95
- schedule_timeout: str
96
- sticky: Union[StickyStrategy.Value, None] # type: ignore[name-defined]
97
- default_priority: int | None
98
- concurrency_expression: ConcurrencyExpression | None
99
- input_validator: Type[BaseModel] | None
100
-
101
-
102
- class WorkflowMeta(type):
103
- def __new__(
104
- cls: Type["WorkflowMeta"],
105
- name: str,
106
- bases: tuple[type, ...],
107
- attrs: dict[str, Any],
108
- ) -> "WorkflowMeta":
109
- def _create_steps_actions_list(name: str) -> StepsType:
110
- return [
111
- (getattr(func, name), attrs.pop(func_name))
112
- for func_name, func in list(attrs.items())
113
- if hasattr(func, name)
114
- ]
115
-
116
- concurrencyActions = _create_steps_actions_list("_concurrency_fn_name")
117
- steps = _create_steps_actions_list("_step_name")
118
-
119
- onFailureSteps = _create_steps_actions_list("_on_failure_step_name")
120
-
121
- # Define __init__ and get_step_order methods
122
- original_init = attrs.get("__init__") # Get the original __init__ if it exists
123
-
124
- def __init__(self: TW, *args: Any, **kwargs: Any) -> None:
125
- if original_init:
126
- original_init(self, *args, **kwargs) # Call original __init__
127
-
128
- def get_service_name(namespace: str) -> str:
129
- return f"{namespace}{name.lower()}"
130
-
131
- @functools.cache
132
- def get_actions(self: TW, namespace: str) -> StepsType:
133
- serviceName = get_service_name(namespace)
134
-
135
- func_actions = [
136
- (serviceName + ":" + func_name, func) for func_name, func in steps
137
- ]
138
- concurrency_actions = [
139
- (serviceName + ":" + func_name, func)
140
- for func_name, func in concurrencyActions
141
- ]
142
- onFailure_actions = [
143
- (serviceName + ":" + func_name, func)
144
- for func_name, func in onFailureSteps
145
- ]
146
-
147
- return func_actions + concurrency_actions + onFailure_actions
148
-
149
- # Add these methods and steps to class attributes
150
- attrs["__init__"] = __init__
151
- attrs["get_actions"] = get_actions
152
-
153
- for step_name, step_func in steps:
154
- attrs[step_name] = step_func
155
-
156
- def get_name(self: TW, namespace: str) -> str:
157
- return namespace + cast(str, attrs["name"])
158
-
159
- attrs["get_name"] = get_name
160
-
161
- cron_triggers = attrs["on_crons"]
162
- version = attrs["version"]
163
- schedule_timeout = attrs["schedule_timeout"]
164
- sticky = attrs["sticky"]
165
- default_priority = attrs["default_priority"]
166
-
167
- @functools.cache
168
- def get_create_opts(self: TW, namespace: str) -> CreateWorkflowVersionOpts:
169
- serviceName = get_service_name(namespace)
170
- name = self.get_name(namespace)
171
- event_triggers = [namespace + event for event in attrs["on_events"]]
172
- createStepOpts: list[CreateWorkflowStepOpts] = [
173
- CreateWorkflowStepOpts(
174
- readable_id=step_name,
175
- action=serviceName + ":" + step_name,
176
- timeout=func._step_timeout or "60s",
177
- inputs="{}",
178
- parents=[x for x in func._step_parents],
179
- retries=func._step_retries,
180
- rate_limits=func._step_rate_limits, # type: ignore[arg-type]
181
- worker_labels=func._step_desired_worker_labels, # type: ignore[arg-type]
182
- backoff_factor=func._step_backoff_factor,
183
- backoff_max_seconds=func._step_backoff_max_seconds,
184
- )
185
- for step_name, func in steps
186
- ]
131
+ self,
132
+ fn: Callable[[Any, Context], R] | Callable[[Any, Context], Awaitable[R]],
133
+ type: StepType,
134
+ name: str = "",
135
+ timeout: str = "60m",
136
+ parents: list[str] = [],
137
+ retries: int = 0,
138
+ rate_limits: list[CreateStepRateLimit] = [],
139
+ desired_worker_labels: dict[str, DesiredWorkerLabels] = {},
140
+ backoff_factor: float | None = None,
141
+ backoff_max_seconds: int | None = None,
142
+ concurrency__max_runs: int | None = None,
143
+ concurrency__limit_strategy: ConcurrencyLimitStrategy | None = None,
144
+ ) -> None:
145
+ self.fn = fn
146
+ self.is_async_function = is_async_fn(fn)
147
+ self.workflow: Union["BaseWorkflow", None] = None
148
+
149
+ self.type = type
150
+ self.timeout = timeout
151
+ self.name = name
152
+ self.parents = parents
153
+ self.retries = retries
154
+ self.rate_limits = rate_limits
155
+ self.desired_worker_labels = desired_worker_labels
156
+ self.backoff_factor = backoff_factor
157
+ self.backoff_max_seconds = backoff_max_seconds
158
+ self.concurrency__max_runs = concurrency__max_runs
159
+ self.concurrency__limit_strategy = concurrency__limit_strategy
160
+
161
+ def call(self, ctx: Context) -> R:
162
+ if not self.is_registered:
163
+ raise ValueError(
164
+ "Only steps that have been registered can be called. To register this step, instantiate its corresponding workflow."
165
+ )
187
166
 
188
- concurrency: WorkflowConcurrencyOpts | None = None
167
+ if self.is_async_function:
168
+ raise TypeError(f"{self.name} is not a sync function. Use `acall` instead.")
189
169
 
190
- if len(concurrencyActions) > 0:
191
- action = concurrencyActions[0]
170
+ sync_fn = self.fn
171
+ if is_sync_fn(sync_fn):
172
+ return sync_fn(self.workflow, ctx)
192
173
 
193
- concurrency = WorkflowConcurrencyOpts(
194
- action=serviceName + ":" + action[0],
195
- max_runs=action[1]._concurrency_max_runs,
196
- limit_strategy=action[1]._concurrency_limit_strategy,
197
- )
174
+ raise TypeError(f"{self.name} is not a sync function. Use `acall` instead.")
198
175
 
199
- if self.concurrency_expression:
200
- concurrency = WorkflowConcurrencyOpts(
201
- expression=self.concurrency_expression.expression,
202
- max_runs=self.concurrency_expression.max_runs,
203
- limit_strategy=self.concurrency_expression.limit_strategy,
204
- )
176
+ async def aio_call(self, ctx: Context) -> R:
177
+ if not self.is_registered:
178
+ raise ValueError(
179
+ "Only steps that have been registered can be called. To register this step, instantiate its corresponding workflow."
180
+ )
205
181
 
206
- if len(concurrencyActions) > 0 and self.concurrency_expression:
207
- raise ValueError(
208
- "Error: Both concurrencyActions and concurrency_expression are defined. Please use only one concurrency configuration method."
209
- )
182
+ if not self.is_async_function:
183
+ raise TypeError(
184
+ f"{self.name} is not an async function. Use `call` instead."
185
+ )
210
186
 
211
- on_failure_job: CreateWorkflowJobOpts | None = None
212
-
213
- if len(onFailureSteps) > 0:
214
- func_name, func = onFailureSteps[0]
215
- on_failure_job = CreateWorkflowJobOpts(
216
- name=name + "-on-failure",
217
- steps=[
218
- CreateWorkflowStepOpts(
219
- readable_id=func_name,
220
- action=serviceName + ":" + func_name,
221
- timeout=func._on_failure_step_timeout or "60s",
222
- inputs="{}",
223
- parents=[],
224
- retries=func._on_failure_step_retries,
225
- rate_limits=func._on_failure_step_rate_limits, # type: ignore[arg-type]
226
- backoff_factor=func._on_failure_step_backoff_factor,
227
- backoff_max_seconds=func._on_failure_step_backoff_max_seconds,
228
- )
229
- ],
230
- )
187
+ async_fn = self.fn
188
+
189
+ if is_async_fn(async_fn):
190
+ return await async_fn(self.workflow, ctx)
191
+
192
+ raise TypeError(f"{self.name} is not an async function. Use `call` instead.")
231
193
 
232
- validated_priority = (
233
- max(1, min(3, default_priority)) if default_priority else None
194
+ @property
195
+ def is_registered(self) -> bool:
196
+ return self.workflow is not None
197
+
198
+
199
+ class Task(Generic[R, TWorkflowInput]):
200
+ def __init__(
201
+ self,
202
+ fn: Callable[[Context], R],
203
+ hatchet: "Hatchet",
204
+ name: str = "",
205
+ on_events: list[str] = [],
206
+ on_crons: list[str] = [],
207
+ version: str = "",
208
+ timeout: str = "60m",
209
+ schedule_timeout: str = "5m",
210
+ sticky: StickyStrategy | None = None,
211
+ retries: int = 0,
212
+ rate_limits: list[RateLimit] = [],
213
+ desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
214
+ concurrency: ConcurrencyExpression | None = None,
215
+ on_failure: Union["Task[R, TWorkflowInput]", None] = None,
216
+ default_priority: int = 1,
217
+ input_validator: Type[TWorkflowInput] | None = None,
218
+ backoff_factor: float | None = None,
219
+ backoff_max_seconds: int | None = None,
220
+ ) -> None:
221
+ def func(_: Any, context: Context) -> R:
222
+ return fn(context)
223
+
224
+ self.hatchet = hatchet
225
+ self.step: Step[R] = hatchet.step(
226
+ name=name or fn.__name__,
227
+ timeout=timeout,
228
+ retries=retries,
229
+ rate_limits=rate_limits,
230
+ desired_worker_labels=desired_worker_labels,
231
+ backoff_factor=backoff_factor,
232
+ backoff_max_seconds=backoff_max_seconds,
233
+ )(func)
234
+ self.on_failure_step = on_failure
235
+ self.workflow_config = WorkflowConfig(
236
+ name=name or fn.__name__,
237
+ on_events=on_events,
238
+ on_crons=on_crons,
239
+ version=version,
240
+ timeout=timeout,
241
+ schedule_timeout=schedule_timeout,
242
+ sticky=sticky,
243
+ default_priority=default_priority,
244
+ concurrency=concurrency,
245
+ input_validator=input_validator or cast(Type[TWorkflowInput], EmptyModel),
246
+ )
247
+
248
+
249
+ @dataclass
250
+ class SpawnWorkflowInput(Generic[TWorkflowInput]):
251
+ input: TWorkflowInput
252
+ key: str | None = None
253
+ options: ChildTriggerWorkflowOptions = field(
254
+ default_factory=ChildTriggerWorkflowOptions
255
+ )
256
+
257
+
258
+ class WorkflowDeclaration(Generic[TWorkflowInput]):
259
+ def __init__(self, config: WorkflowConfig, hatchet: Union["Hatchet", None]):
260
+ self.config = config
261
+ self.hatchet = hatchet
262
+
263
+ def run(self, input: TWorkflowInput | None = None) -> WorkflowRunRef:
264
+ if not self.hatchet:
265
+ raise ValueError("Hatchet client is not initialized.")
266
+
267
+ return self.hatchet.admin.run_workflow(
268
+ workflow_name=self.config.name, input=input.model_dump() if input else {}
269
+ )
270
+
271
+ def get_workflow_input(self, ctx: Context) -> TWorkflowInput:
272
+ return cast(
273
+ TWorkflowInput,
274
+ self.config.input_validator.model_validate(ctx.workflow_input),
275
+ )
276
+
277
+ async def aio_spawn_many(
278
+ self, ctx: Context, spawn_inputs: list[SpawnWorkflowInput[TWorkflowInput]]
279
+ ) -> list[WorkflowRunRef]:
280
+ inputs = [
281
+ ChildWorkflowRunDict(
282
+ workflow_name=self.config.name,
283
+ input=spawn_input.input.model_dump(),
284
+ key=spawn_input.key,
285
+ options=spawn_input.options,
234
286
  )
235
- if validated_priority != default_priority:
236
- logger.warning(
237
- "Warning: Default Priority Must be between 1 and 3 -- inclusively. Adjusted to be within the range."
238
- )
287
+ for spawn_input in spawn_inputs
288
+ ]
289
+ return await ctx.aio_spawn_workflows(inputs)
290
+
291
+ async def aio_spawn_one(
292
+ self,
293
+ ctx: Context,
294
+ input: TWorkflowInput,
295
+ key: str | None = None,
296
+ options: ChildTriggerWorkflowOptions = ChildTriggerWorkflowOptions(),
297
+ ) -> WorkflowRunRef:
298
+ return await ctx.aio_spawn_workflow(
299
+ workflow_name=self.config.name,
300
+ input=input.model_dump(),
301
+ key=key,
302
+ options=options,
303
+ )
304
+
305
+ def spawn_many(
306
+ self, ctx: Context, spawn_inputs: list[SpawnWorkflowInput[TWorkflowInput]]
307
+ ) -> list[WorkflowRunRef]:
308
+ inputs = [
309
+ ChildWorkflowRunDict(
310
+ workflow_name=self.config.name,
311
+ input=spawn_input.input.model_dump(),
312
+ key=spawn_input.key,
313
+ options=spawn_input.options,
314
+ )
315
+ for spawn_input in spawn_inputs
316
+ ]
317
+
318
+ return ctx.spawn_workflows(inputs)
319
+
320
+ def spawn_one(
321
+ self,
322
+ ctx: Context,
323
+ input: TWorkflowInput,
324
+ key: str | None = None,
325
+ options: ChildTriggerWorkflowOptions = ChildTriggerWorkflowOptions(),
326
+ ) -> WorkflowRunRef:
327
+ return ctx.spawn_workflow(
328
+ workflow_name=self.config.name,
329
+ input=input.model_dump(),
330
+ key=key,
331
+ options=options,
332
+ )
333
+
334
+ def schedule(
335
+ self,
336
+ schedules: list[datetime | timestamp_pb2.Timestamp],
337
+ input: TWorkflowInput,
338
+ options: ScheduleTriggerWorkflowOptions = ScheduleTriggerWorkflowOptions(),
339
+ ) -> WorkflowVersion:
340
+ if not self.hatchet:
341
+ raise ValueError("Hatchet client is not initialized.")
342
+
343
+ return self.hatchet.admin.schedule_workflow(
344
+ name=self.config.name,
345
+ schedules=schedules,
346
+ input=input.model_dump(),
347
+ options=options,
348
+ )
349
+
350
+ async def aio_schedule(
351
+ self,
352
+ schedules: list[datetime | timestamp_pb2.Timestamp],
353
+ input: TWorkflowInput,
354
+ options: ScheduleTriggerWorkflowOptions = ScheduleTriggerWorkflowOptions(),
355
+ ) -> WorkflowVersion:
356
+ if not self.hatchet:
357
+ raise ValueError("Hatchet client is not initialized.")
358
+
359
+ return await self.hatchet.admin.aio_schedule_workflow(
360
+ name=self.config.name,
361
+ schedules=schedules,
362
+ input=input.model_dump(),
363
+ options=options,
364
+ )
365
+
366
+
367
+ class BaseWorkflow:
368
+ """
369
+ A Hatchet workflow implementation base. This class should be inherited by all workflow implementations.
370
+
371
+ Configuration is passed to the workflow implementation via the `config` attribute.
372
+ """
373
+
374
+ config: WorkflowConfig = WorkflowConfig()
375
+
376
+ def __init__(self) -> None:
377
+ self.config.name = self.config.name or str(self.__class__.__name__)
378
+
379
+ for step in self.steps:
380
+ step.workflow = self
381
+
382
+ def get_service_name(self, namespace: str) -> str:
383
+ return f"{namespace}{self.config.name.lower()}"
384
+
385
+ def _get_steps_by_type(self, step_type: StepType) -> list[Step[Any]]:
386
+ return [
387
+ attr
388
+ for _, attr in self.__class__.__dict__.items()
389
+ if isinstance(attr, Step) and attr.type == step_type
390
+ ]
391
+
392
+ @property
393
+ def on_failure_steps(self) -> list[Step[Any]]:
394
+ return self._get_steps_by_type(StepType.ON_FAILURE)
395
+
396
+ @property
397
+ def concurrency_actions(self) -> list[Step[Any]]:
398
+ return self._get_steps_by_type(StepType.CONCURRENCY)
399
+
400
+ @property
401
+ def default_steps(self) -> list[Step[Any]]:
402
+ return self._get_steps_by_type(StepType.DEFAULT)
403
+
404
+ @property
405
+ def steps(self) -> list[Step[Any]]:
406
+ return self.default_steps + self.concurrency_actions + self.on_failure_steps
239
407
 
240
- return CreateWorkflowVersionOpts(
241
- name=name,
242
- kind=WorkflowKind.DAG,
243
- version=version,
244
- event_triggers=event_triggers,
245
- cron_triggers=cron_triggers,
246
- schedule_timeout=schedule_timeout,
247
- sticky=sticky,
248
- jobs=[
249
- CreateWorkflowJobOpts(
250
- name=name,
251
- steps=createStepOpts,
408
+ def create_action_name(self, namespace: str, step: Step[Any]) -> str:
409
+ return self.get_service_name(namespace) + ":" + step.name
410
+
411
+ def get_name(self, namespace: str) -> str:
412
+ return namespace + self.config.name
413
+
414
+ def validate_concurrency_actions(
415
+ self, service_name: str
416
+ ) -> WorkflowConcurrencyOpts | None:
417
+ if len(self.concurrency_actions) > 0 and self.config.concurrency:
418
+ raise ValueError(
419
+ "Error: Both concurrencyActions and concurrency_expression are defined. Please use only one concurrency configuration method."
420
+ )
421
+
422
+ if len(self.concurrency_actions) > 0:
423
+ action = self.concurrency_actions[0]
424
+
425
+ return WorkflowConcurrencyOpts(
426
+ action=service_name + ":" + action.name,
427
+ max_runs=action.concurrency__max_runs,
428
+ limit_strategy=maybe_int_to_str(
429
+ convert_python_enum_to_proto(
430
+ action.concurrency__limit_strategy,
431
+ ConcurrencyLimitStrategyProto,
252
432
  )
253
- ],
254
- on_failure_job=on_failure_job,
255
- concurrency=concurrency,
256
- default_priority=validated_priority,
433
+ ),
434
+ )
435
+
436
+ if self.config.concurrency:
437
+ return WorkflowConcurrencyOpts(
438
+ expression=self.config.concurrency.expression,
439
+ max_runs=self.config.concurrency.max_runs,
440
+ limit_strategy=self.config.concurrency.limit_strategy,
257
441
  )
258
442
 
259
- attrs["get_create_opts"] = get_create_opts
443
+ return None
444
+
445
+ def validate_on_failure_steps(
446
+ self, name: str, service_name: str
447
+ ) -> CreateWorkflowJobOpts | None:
448
+ if not self.on_failure_steps:
449
+ return None
260
450
 
261
- return super(WorkflowMeta, cls).__new__(cls, name, bases, attrs)
451
+ on_failure_step = next(iter(self.on_failure_steps))
452
+
453
+ return CreateWorkflowJobOpts(
454
+ name=name + "-on-failure",
455
+ steps=[
456
+ CreateWorkflowStepOpts(
457
+ readable_id=on_failure_step.name,
458
+ action=service_name + ":" + on_failure_step.name,
459
+ timeout=on_failure_step.timeout or "60s",
460
+ inputs="{}",
461
+ parents=[],
462
+ retries=on_failure_step.retries,
463
+ rate_limits=on_failure_step.rate_limits,
464
+ backoff_factor=on_failure_step.backoff_factor,
465
+ backoff_max_seconds=on_failure_step.backoff_max_seconds,
466
+ )
467
+ ],
468
+ )
469
+
470
+ def validate_priority(self, default_priority: int | None) -> int | None:
471
+ validated_priority = (
472
+ max(1, min(3, default_priority)) if default_priority else None
473
+ )
474
+ if validated_priority != default_priority:
475
+ logger.warning(
476
+ "Warning: Default Priority Must be between 1 and 3 -- inclusively. Adjusted to be within the range."
477
+ )
478
+
479
+ return validated_priority
480
+
481
+ def get_create_opts(self, namespace: str) -> CreateWorkflowVersionOpts:
482
+ service_name = self.get_service_name(namespace)
483
+
484
+ name = self.get_name(namespace)
485
+ event_triggers = [namespace + event for event in self.config.on_events]
486
+
487
+ create_step_opts = [
488
+ CreateWorkflowStepOpts(
489
+ readable_id=step.name,
490
+ action=service_name + ":" + step.name,
491
+ timeout=step.timeout or "60s",
492
+ inputs="{}",
493
+ parents=[x for x in step.parents],
494
+ retries=step.retries,
495
+ rate_limits=step.rate_limits,
496
+ worker_labels=step.desired_worker_labels,
497
+ backoff_factor=step.backoff_factor,
498
+ backoff_max_seconds=step.backoff_max_seconds,
499
+ )
500
+ for step in self.steps
501
+ if step.type == StepType.DEFAULT
502
+ ]
503
+
504
+ concurrency = self.validate_concurrency_actions(service_name)
505
+ on_failure_job = self.validate_on_failure_steps(name, service_name)
506
+ validated_priority = self.validate_priority(self.config.default_priority)
507
+
508
+ return CreateWorkflowVersionOpts(
509
+ name=name,
510
+ kind=WorkflowKind.DAG,
511
+ version=self.config.version,
512
+ event_triggers=event_triggers,
513
+ cron_triggers=self.config.on_crons,
514
+ schedule_timeout=self.config.schedule_timeout,
515
+ sticky=maybe_int_to_str(
516
+ convert_python_enum_to_proto(self.config.sticky, StickyStrategyProto)
517
+ ),
518
+ jobs=[
519
+ CreateWorkflowJobOpts(
520
+ name=name,
521
+ steps=create_step_opts,
522
+ )
523
+ ],
524
+ on_failure_job=on_failure_job,
525
+ concurrency=concurrency,
526
+ default_priority=validated_priority,
527
+ )