hatchet-sdk 0.40.0a9__py3-none-any.whl → 0.42.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (152) hide show
  1. hatchet_sdk/clients/admin.py +129 -59
  2. hatchet_sdk/clients/dispatcher/action_listener.py +25 -2
  3. hatchet_sdk/clients/events.py +91 -52
  4. hatchet_sdk/clients/rest/__init__.py +21 -0
  5. hatchet_sdk/clients/rest/api/api_token_api.py +12 -9
  6. hatchet_sdk/clients/rest/api/default_api.py +24 -18
  7. hatchet_sdk/clients/rest/api/event_api.py +32 -24
  8. hatchet_sdk/clients/rest/api/github_api.py +4 -3
  9. hatchet_sdk/clients/rest/api/log_api.py +4 -3
  10. hatchet_sdk/clients/rest/api/metadata_api.py +12 -9
  11. hatchet_sdk/clients/rest/api/rate_limits_api.py +7 -4
  12. hatchet_sdk/clients/rest/api/slack_api.py +8 -6
  13. hatchet_sdk/clients/rest/api/sns_api.py +12 -9
  14. hatchet_sdk/clients/rest/api/step_run_api.py +28 -21
  15. hatchet_sdk/clients/rest/api/tenant_api.py +67 -49
  16. hatchet_sdk/clients/rest/api/user_api.py +24 -18
  17. hatchet_sdk/clients/rest/api/worker_api.py +12 -9
  18. hatchet_sdk/clients/rest/api/workflow_api.py +3073 -936
  19. hatchet_sdk/clients/rest/api/workflow_run_api.py +669 -21
  20. hatchet_sdk/clients/rest/api_client.py +34 -11
  21. hatchet_sdk/clients/rest/configuration.py +161 -36
  22. hatchet_sdk/clients/rest/models/__init__.py +21 -0
  23. hatchet_sdk/clients/rest/models/api_errors.py +3 -3
  24. hatchet_sdk/clients/rest/models/bulk_create_event_request.py +3 -3
  25. hatchet_sdk/clients/rest/models/bulk_create_event_response.py +3 -3
  26. hatchet_sdk/clients/{cloud_rest/models/managed_worker_create_request_build_config_steps_inner.py → rest/models/create_cron_workflow_trigger_request.py} +18 -14
  27. hatchet_sdk/clients/{cloud_rest/models/github_app_list_installations200_response_rows_inner.py → rest/models/cron_workflows.py} +54 -21
  28. hatchet_sdk/clients/{cloud_rest/models/log_list200_response.py → rest/models/cron_workflows_list.py} +13 -22
  29. hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py +37 -0
  30. hatchet_sdk/clients/rest/models/event_list.py +3 -3
  31. hatchet_sdk/clients/rest/models/get_step_run_diff_response.py +3 -3
  32. hatchet_sdk/clients/rest/models/job.py +3 -3
  33. hatchet_sdk/clients/rest/models/job_run.py +3 -3
  34. hatchet_sdk/clients/rest/models/list_api_tokens_response.py +3 -3
  35. hatchet_sdk/clients/rest/models/list_pull_requests_response.py +3 -3
  36. hatchet_sdk/clients/rest/models/list_slack_webhooks.py +3 -3
  37. hatchet_sdk/clients/rest/models/list_sns_integrations.py +3 -3
  38. hatchet_sdk/clients/rest/models/log_line_list.py +3 -3
  39. hatchet_sdk/clients/rest/models/rate_limit_list.py +3 -3
  40. hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py +3 -3
  41. hatchet_sdk/clients/{cloud_rest/models/log_list200_response_rows_inner.py → rest/models/schedule_workflow_run_request.py} +12 -12
  42. hatchet_sdk/clients/rest/models/scheduled_run_status.py +42 -0
  43. hatchet_sdk/clients/rest/models/scheduled_workflows.py +153 -0
  44. hatchet_sdk/clients/{cloud_rest/models/managed_worker_list200_response.py → rest/models/scheduled_workflows_list.py} +13 -22
  45. hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
  46. hatchet_sdk/clients/rest/models/step_run_archive_list.py +3 -3
  47. hatchet_sdk/clients/rest/models/step_run_event_list.py +3 -3
  48. hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py +3 -3
  49. hatchet_sdk/clients/rest/models/tenant_invite_list.py +3 -3
  50. hatchet_sdk/clients/rest/models/tenant_list.py +3 -3
  51. hatchet_sdk/clients/rest/models/tenant_member_list.py +3 -3
  52. hatchet_sdk/clients/rest/models/tenant_queue_metrics.py +16 -0
  53. hatchet_sdk/clients/rest/models/tenant_resource_policy.py +3 -3
  54. hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py +1 -1
  55. hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py +3 -3
  56. hatchet_sdk/clients/rest/models/webhook_worker_list_response.py +3 -3
  57. hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py +3 -3
  58. hatchet_sdk/clients/rest/models/worker.py +20 -9
  59. hatchet_sdk/clients/rest/models/worker_list.py +3 -3
  60. hatchet_sdk/clients/{cloud_rest/models/tenant_billing_state_get200_response_payment_methods_inner.py → rest/models/worker_runtime_info.py} +23 -19
  61. hatchet_sdk/clients/rest/models/worker_runtime_sdks.py +38 -0
  62. hatchet_sdk/clients/rest/models/workflow.py +9 -9
  63. hatchet_sdk/clients/rest/models/workflow_list.py +3 -3
  64. hatchet_sdk/clients/rest/models/workflow_run.py +3 -3
  65. hatchet_sdk/clients/rest/models/workflow_run_list.py +3 -3
  66. hatchet_sdk/clients/rest/models/workflow_run_shape.py +3 -3
  67. hatchet_sdk/clients/rest/models/workflow_runs_metrics.py +1 -5
  68. hatchet_sdk/clients/rest/models/workflow_triggers.py +6 -6
  69. hatchet_sdk/clients/rest/models/workflow_version.py +3 -3
  70. hatchet_sdk/clients/rest/rest.py +3 -3
  71. hatchet_sdk/clients/rest_client.py +200 -21
  72. hatchet_sdk/contracts/dispatcher_pb2.py +71 -67
  73. hatchet_sdk/contracts/dispatcher_pb2.pyi +31 -2
  74. hatchet_sdk/contracts/events_pb2.pyi +2 -0
  75. hatchet_sdk/contracts/workflows_pb2.py +42 -40
  76. hatchet_sdk/contracts/workflows_pb2.pyi +24 -6
  77. hatchet_sdk/features/cron.py +286 -0
  78. hatchet_sdk/features/scheduled.py +248 -0
  79. hatchet_sdk/hatchet.py +80 -79
  80. hatchet_sdk/loader.py +37 -14
  81. hatchet_sdk/utils/serialization.py +15 -0
  82. hatchet_sdk/utils/tracing.py +67 -0
  83. hatchet_sdk/worker/runner/runner.py +158 -112
  84. hatchet_sdk/worker/worker.py +1 -17
  85. hatchet_sdk/workflow.py +4 -0
  86. {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.42.0.dist-info}/METADATA +8 -2
  87. {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.42.0.dist-info}/RECORD +89 -143
  88. {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.42.0.dist-info}/entry_points.txt +1 -1
  89. hatchet_sdk/clients/cloud_rest/__init__.py +0 -186
  90. hatchet_sdk/clients/cloud_rest/api/__init__.py +0 -14
  91. hatchet_sdk/clients/cloud_rest/api/billing_api.py +0 -819
  92. hatchet_sdk/clients/cloud_rest/api/build_api.py +0 -298
  93. hatchet_sdk/clients/cloud_rest/api/feature_flags_api.py +0 -295
  94. hatchet_sdk/clients/cloud_rest/api/github_api.py +0 -1347
  95. hatchet_sdk/clients/cloud_rest/api/log_api.py +0 -971
  96. hatchet_sdk/clients/cloud_rest/api/managed_worker_api.py +0 -2546
  97. hatchet_sdk/clients/cloud_rest/api/metadata_api.py +0 -265
  98. hatchet_sdk/clients/cloud_rest/api/metrics_api.py +0 -1026
  99. hatchet_sdk/clients/cloud_rest/api/tenant_api.py +0 -301
  100. hatchet_sdk/clients/cloud_rest/api/user_api.py +0 -473
  101. hatchet_sdk/clients/cloud_rest/api/workflow_api.py +0 -369
  102. hatchet_sdk/clients/cloud_rest/api_client.py +0 -727
  103. hatchet_sdk/clients/cloud_rest/api_response.py +0 -22
  104. hatchet_sdk/clients/cloud_rest/configuration.py +0 -488
  105. hatchet_sdk/clients/cloud_rest/exceptions.py +0 -200
  106. hatchet_sdk/clients/cloud_rest/models/__init__.py +0 -157
  107. hatchet_sdk/clients/cloud_rest/models/billing_portal_link_get200_response.py +0 -85
  108. hatchet_sdk/clients/cloud_rest/models/build_get200_response.py +0 -121
  109. hatchet_sdk/clients/cloud_rest/models/github_app_list_branches200_response_inner.py +0 -86
  110. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response.py +0 -119
  111. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_pagination.py +0 -95
  112. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_rows_inner_metadata.py +0 -98
  113. hatchet_sdk/clients/cloud_rest/models/github_app_list_repos200_response_inner.py +0 -86
  114. hatchet_sdk/clients/cloud_rest/models/infra_as_code_create_request.py +0 -107
  115. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner.py +0 -136
  116. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_event.py +0 -83
  117. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly.py +0 -100
  118. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly_app.py +0 -86
  119. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_log.py +0 -83
  120. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request.py +0 -128
  121. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_build_config.py +0 -121
  122. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_runtime_config.py +0 -166
  123. hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response.py +0 -119
  124. hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response_rows_inner.py +0 -117
  125. hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response.py +0 -119
  126. hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response_rows_inner.py +0 -113
  127. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner.py +0 -154
  128. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config.py +0 -151
  129. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config_steps_inner.py +0 -109
  130. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_runtime_configs_inner.py +0 -171
  131. hatchet_sdk/clients/cloud_rest/models/managed_worker_update_request.py +0 -131
  132. hatchet_sdk/clients/cloud_rest/models/metadata_get200_response.py +0 -101
  133. hatchet_sdk/clients/cloud_rest/models/metadata_get400_response.py +0 -105
  134. hatchet_sdk/clients/cloud_rest/models/metadata_get400_response_errors_inner.py +0 -102
  135. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner.py +0 -108
  136. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner.py +0 -102
  137. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram.py +0 -113
  138. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram_buckets_inner.py +0 -93
  139. hatchet_sdk/clients/cloud_rest/models/runtime_config_list_actions200_response.py +0 -83
  140. hatchet_sdk/clients/cloud_rest/models/subscription_upsert200_response.py +0 -114
  141. hatchet_sdk/clients/cloud_rest/models/subscription_upsert_request.py +0 -88
  142. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response.py +0 -170
  143. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_coupons_inner.py +0 -137
  144. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_plans_inner.py +0 -103
  145. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_subscription.py +0 -114
  146. hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response.py +0 -107
  147. hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response_results_inner.py +0 -105
  148. hatchet_sdk/clients/cloud_rest/rest.py +0 -182
  149. hatchet_sdk/compute/__init__.py +0 -0
  150. hatchet_sdk/compute/configs.py +0 -34
  151. hatchet_sdk/compute/managed_compute.py +0 -111
  152. {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.42.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,248 @@
1
+ import datetime
2
+ from typing import Any, Coroutine, Dict, List, Optional, Union
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from hatchet_sdk.client import Client
7
+ from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
8
+ from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
9
+ CronWorkflowsOrderByField,
10
+ )
11
+ from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
12
+ from hatchet_sdk.clients.rest.models.scheduled_workflows_list import (
13
+ ScheduledWorkflowsList,
14
+ )
15
+ from hatchet_sdk.clients.rest.models.workflow_run_order_by_direction import (
16
+ WorkflowRunOrderByDirection,
17
+ )
18
+
19
+
20
+ class CreateScheduledTriggerInput(BaseModel):
21
+ """
22
+ Schema for creating a scheduled workflow run.
23
+
24
+ Attributes:
25
+ input (Dict[str, Any]): The input data for the scheduled workflow.
26
+ additional_metadata (Dict[str, str]): Additional metadata associated with the future run (e.g. ["key1:value1", "key2:value2"]).
27
+ trigger_at (Optional[datetime.datetime]): The datetime when the run should be triggered.
28
+ """
29
+
30
+ input: Dict[str, Any] = {}
31
+ additional_metadata: Dict[str, str] = {}
32
+ trigger_at: Optional[datetime.datetime] = None
33
+
34
+
35
+ class ScheduledClient:
36
+ """
37
+ Client for managing scheduled workflows synchronously.
38
+
39
+ Attributes:
40
+ _client (Client): The underlying client used to interact with the REST API.
41
+ aio (ScheduledClientAsync): Asynchronous counterpart of ScheduledClient.
42
+ """
43
+
44
+ _client: Client
45
+
46
+ def __init__(self, _client: Client) -> None:
47
+ """
48
+ Initializes the ScheduledClient with a given Client instance.
49
+
50
+ Args:
51
+ _client (Client): The client instance to be used for REST interactions.
52
+ """
53
+ self._client = _client
54
+ self.aio: "ScheduledClientAsync" = ScheduledClientAsync(_client)
55
+
56
+ def create(
57
+ self,
58
+ workflow_name: str,
59
+ trigger_at: datetime.datetime,
60
+ input: Dict[str, Any],
61
+ additional_metadata: Dict[str, str],
62
+ ) -> ScheduledWorkflows:
63
+ """
64
+ Creates a new scheduled workflow run asynchronously.
65
+
66
+ Args:
67
+ workflow_name (str): The name of the scheduled workflow.
68
+ trigger_at (datetime.datetime): The datetime when the run should be triggered.
69
+ input (Dict[str, Any]): The input data for the scheduled workflow.
70
+ additional_metadata (Dict[str, str]): Additional metadata associated with the future run as a key-value pair (e.g. {"key1": "value1", "key2": "value2"}).
71
+
72
+ Returns:
73
+ ScheduledWorkflows: The created scheduled workflow instance.
74
+ """
75
+
76
+ validated_input = CreateScheduledTriggerInput(
77
+ trigger_at=trigger_at, input=input, additional_metadata=additional_metadata
78
+ )
79
+
80
+ return self._client.rest.schedule_create(
81
+ workflow_name,
82
+ validated_input.trigger_at,
83
+ validated_input.input,
84
+ validated_input.additional_metadata,
85
+ )
86
+
87
+ def delete(self, scheduled: Union[str, ScheduledWorkflows]) -> None:
88
+ """
89
+ Deletes a scheduled workflow run.
90
+
91
+ Args:
92
+ scheduled (Union[str, ScheduledWorkflows]): The scheduled workflow trigger ID or ScheduledWorkflows instance to delete.
93
+ """
94
+ id_ = scheduled
95
+ if isinstance(scheduled, ScheduledWorkflows):
96
+ id_ = scheduled.metadata.id
97
+ self._client.rest.schedule_delete(id_)
98
+
99
+ def list(
100
+ self,
101
+ offset: Optional[int] = None,
102
+ limit: Optional[int] = None,
103
+ workflow_id: Optional[str] = None,
104
+ additional_metadata: Optional[List[str]] = None,
105
+ order_by_field: Optional[CronWorkflowsOrderByField] = None,
106
+ order_by_direction: Optional[WorkflowRunOrderByDirection] = None,
107
+ ) -> ScheduledWorkflowsList:
108
+ """
109
+ Retrieves a list of scheduled workflows based on provided filters.
110
+
111
+ Args:
112
+ offset (Optional[int]): The starting point for the list.
113
+ limit (Optional[int]): The maximum number of items to return.
114
+ workflow_id (Optional[str]): Filter by specific workflow ID.
115
+ additional_metadata (Optional[List[str]]): Filter by additional metadata keys (e.g. ["key1:value1", "key2:value2"]).
116
+ order_by_field (Optional[CronWorkflowsOrderByField]): Field to order the results by.
117
+ order_by_direction (Optional[WorkflowRunOrderByDirection]): Direction to order the results.
118
+
119
+ Returns:
120
+ List[ScheduledWorkflows]: A list of scheduled workflows matching the criteria.
121
+ """
122
+ return self._client.rest.schedule_list(
123
+ offset=offset,
124
+ limit=limit,
125
+ workflow_id=workflow_id,
126
+ additional_metadata=additional_metadata,
127
+ order_by_field=order_by_field,
128
+ order_by_direction=order_by_direction,
129
+ )
130
+
131
+ def get(self, scheduled: Union[str, ScheduledWorkflows]) -> ScheduledWorkflows:
132
+ """
133
+ Retrieves a specific scheduled workflow by scheduled run trigger ID.
134
+
135
+ Args:
136
+ scheduled (Union[str, ScheduledWorkflows]): The scheduled workflow trigger ID or ScheduledWorkflows instance to retrieve.
137
+
138
+ Returns:
139
+ ScheduledWorkflows: The requested scheduled workflow instance.
140
+ """
141
+ id_ = scheduled
142
+ if isinstance(scheduled, ScheduledWorkflows):
143
+ id_ = scheduled.metadata.id
144
+ return self._client.rest.schedule_get(id_)
145
+
146
+
147
+ class ScheduledClientAsync:
148
+ """
149
+ Asynchronous client for managing scheduled workflows.
150
+
151
+ Attributes:
152
+ _client (Client): The underlying client used to interact with the REST API asynchronously.
153
+ """
154
+
155
+ _client: Client
156
+
157
+ def __init__(self, _client: Client) -> None:
158
+ """
159
+ Initializes the ScheduledClientAsync with a given Client instance.
160
+
161
+ Args:
162
+ _client (Client): The client instance to be used for asynchronous REST interactions.
163
+ """
164
+ self._client = _client
165
+
166
+ async def create(
167
+ self,
168
+ workflow_name: str,
169
+ trigger_at: datetime.datetime,
170
+ input: Dict[str, Any],
171
+ additional_metadata: Dict[str, str],
172
+ ) -> ScheduledWorkflows:
173
+ """
174
+ Creates a new scheduled workflow run asynchronously.
175
+
176
+ Args:
177
+ workflow_name (str): The name of the scheduled workflow.
178
+ trigger_at (datetime.datetime): The datetime when the run should be triggered.
179
+ input (Dict[str, Any]): The input data for the scheduled workflow.
180
+ additional_metadata (Dict[str, str]): Additional metadata associated with the future run.
181
+
182
+ Returns:
183
+ ScheduledWorkflows: The created scheduled workflow instance.
184
+ """
185
+ return await self._client.rest.aio.schedule_create(
186
+ workflow_name, trigger_at, input, additional_metadata
187
+ )
188
+
189
+ async def delete(self, scheduled: Union[str, ScheduledWorkflows]) -> None:
190
+ """
191
+ Deletes a scheduled workflow asynchronously.
192
+
193
+ Args:
194
+ scheduled (Union[str, ScheduledWorkflows]): The scheduled workflow trigger ID or ScheduledWorkflows instance to delete.
195
+ """
196
+ id_ = scheduled
197
+ if isinstance(scheduled, ScheduledWorkflows):
198
+ id_ = scheduled.metadata.id
199
+ await self._client.rest.aio.schedule_delete(id_)
200
+
201
+ async def list(
202
+ self,
203
+ offset: Optional[int] = None,
204
+ limit: Optional[int] = None,
205
+ workflow_id: Optional[str] = None,
206
+ additional_metadata: Optional[List[str]] = None,
207
+ order_by_field: Optional[CronWorkflowsOrderByField] = None,
208
+ order_by_direction: Optional[WorkflowRunOrderByDirection] = None,
209
+ ) -> ScheduledWorkflowsList:
210
+ """
211
+ Retrieves a list of scheduled workflows based on provided filters asynchronously.
212
+
213
+ Args:
214
+ offset (Optional[int]): The starting point for the list.
215
+ limit (Optional[int]): The maximum number of items to return.
216
+ workflow_id (Optional[str]): Filter by specific workflow ID.
217
+ additional_metadata (Optional[List[str]]): Filter by additional metadata keys (e.g. ["key1:value1", "key2:value2"]).
218
+ order_by_field (Optional[CronWorkflowsOrderByField]): Field to order the results by.
219
+ order_by_direction (Optional[WorkflowRunOrderByDirection]): Direction to order the results.
220
+
221
+ Returns:
222
+ ScheduledWorkflowsList: A list of scheduled workflows matching the criteria.
223
+ """
224
+ return await self._client.rest.aio.schedule_list(
225
+ offset=offset,
226
+ limit=limit,
227
+ workflow_id=workflow_id,
228
+ additional_metadata=additional_metadata,
229
+ order_by_field=order_by_field,
230
+ order_by_direction=order_by_direction,
231
+ )
232
+
233
+ async def get(
234
+ self, scheduled: Union[str, ScheduledWorkflows]
235
+ ) -> ScheduledWorkflows:
236
+ """
237
+ Retrieves a specific scheduled workflow by scheduled run trigger ID asynchronously.
238
+
239
+ Args:
240
+ scheduled (Union[str, ScheduledWorkflows]): The scheduled workflow trigger ID or ScheduledWorkflows instance to retrieve.
241
+
242
+ Returns:
243
+ ScheduledWorkflows: The requested scheduled workflow instance.
244
+ """
245
+ id_ = scheduled
246
+ if isinstance(scheduled, ScheduledWorkflows):
247
+ id_ = scheduled.metadata.id
248
+ return await self._client.rest.aio.schedule_get(id_)
hatchet_sdk/hatchet.py CHANGED
@@ -1,31 +1,43 @@
1
1
  import asyncio
2
2
  import logging
3
- from typing import List, Optional
3
+ from typing import Any, Callable, Optional, ParamSpec, TypeVar
4
4
 
5
5
  from typing_extensions import deprecated
6
6
 
7
7
  from hatchet_sdk.clients.rest_client import RestApi
8
- from hatchet_sdk.compute.configs import Compute
9
- from hatchet_sdk.contracts.workflows_pb2 import (
8
+
9
+ ## TODO: These type stubs need to be updated to mass MyPy, and then we can remove this ignore
10
+ ## There are file-level type ignore lines in the corresponding .pyi files.
11
+ from hatchet_sdk.contracts.workflows_pb2 import ( # type: ignore[attr-defined]
10
12
  ConcurrencyLimitStrategy,
11
13
  CreateStepRateLimit,
12
14
  DesiredWorkerLabels,
13
15
  StickyStrategy,
14
16
  )
17
+ from hatchet_sdk.features.cron import CronClient
18
+ from hatchet_sdk.features.scheduled import ScheduledClient
15
19
  from hatchet_sdk.labels import DesiredWorkerLabel
16
20
  from hatchet_sdk.loader import ClientConfig, ConfigLoader
17
21
  from hatchet_sdk.rate_limit import RateLimit
18
22
 
19
23
  from .client import Client, new_client, new_client_raw
24
+ from .clients.admin import AdminClient
25
+ from .clients.dispatcher.dispatcher import DispatcherClient
26
+ from .clients.events import EventClient
27
+ from .clients.run_event_listener import RunEventListenerClient
20
28
  from .logger import logger
21
- from .worker import Worker
29
+ from .worker.worker import Worker
22
30
  from .workflow import ConcurrencyExpression, WorkflowMeta
23
31
 
32
+ P = ParamSpec("P")
33
+ R = TypeVar("R")
34
+
24
35
 
25
- def workflow(
36
+ ## TODO: Fix return type here to properly type hint the metaclass
37
+ def workflow( # type: ignore[no-untyped-def]
26
38
  name: str = "",
27
- on_events: list | None = None,
28
- on_crons: list | None = None,
39
+ on_events: list[str] | None = None,
40
+ on_crons: list[str] | None = None,
29
41
  version: str = "",
30
42
  timeout: str = "60m",
31
43
  schedule_timeout: str = "5m",
@@ -33,27 +45,10 @@ def workflow(
33
45
  default_priority: int | None = None,
34
46
  concurrency: ConcurrencyExpression | None = None,
35
47
  ):
36
- """
37
- Decorator to mark a class as a workflow.
38
-
39
- Args:
40
- name (str, optional): The name of the workflow. Defaults to an empty string.
41
- on_events (list, optional): A list of events that trigger the workflow. Defaults to None.
42
- on_crons (list, optional): A list of cron expressions that trigger the workflow. Defaults to None.
43
- version (str, optional): The version of the workflow. Defaults to an empty string.
44
- timeout (str, optional): The timeout for the workflow. Defaults to "60m".
45
- schedule_timeout (str, optional): The schedule timeout for the workflow. Defaults to "5m".
46
- sticky (StickyStrategy, optional): The sticky strategy for the workflow. Defaults to None.
47
- default_priority (int, optional): The default priority for the workflow. Defaults to None.
48
- concurrency (ConcurrencyExpression, optional): The concurrency expression for the workflow. Defaults to None.
49
-
50
- Returns:
51
- function: The decorated class with workflow metadata.
52
- """
53
48
  on_events = on_events or []
54
49
  on_crons = on_crons or []
55
50
 
56
- def inner(cls) -> WorkflowMeta:
51
+ def inner(cls: Any) -> WorkflowMeta:
57
52
  cls.on_events = on_events
58
53
  cls.on_crons = on_crons
59
54
  cls.name = name or str(cls.__name__)
@@ -65,7 +60,9 @@ def workflow(
65
60
  cls.concurrency_expression = concurrency
66
61
  # Define a new class with the same name and bases as the original, but
67
62
  # with WorkflowMeta as its metaclass
68
- return WorkflowMeta(cls.name, cls.__bases__, dict(cls.__dict__))
63
+
64
+ ## TODO: Figure out how to type this metaclass correctly
65
+ return WorkflowMeta(cls.name, cls.__bases__, dict(cls.__dict__)) # type: ignore[no-untyped-call]
69
66
 
70
67
  return inner
71
68
 
@@ -73,30 +70,16 @@ def workflow(
73
70
  def step(
74
71
  name: str = "",
75
72
  timeout: str = "",
76
- parents: List[str] | None = None,
73
+ parents: list[str] | None = None,
77
74
  retries: int = 0,
78
- rate_limits: List[RateLimit] | None = None,
79
- desired_worker_labels: dict[str:DesiredWorkerLabel] = {},
80
- compute: Compute | None = None,
81
- ):
82
- """
83
- Decorator to mark a function as a step in a workflow.
84
-
85
- Args:
86
- name (str, optional): The name of the step. Defaults to the function name.
87
- timeout (str, optional): The timeout for the step. Defaults to an empty string.
88
- parents (List[str], optional): A list of parent step names. Defaults to an empty list.
89
- retries (int, optional): The number of retries for the step. Defaults to 0.
90
- rate_limits (List[RateLimit], optional): A list of rate limits for the step. Defaults to None.
91
- desired_worker_labels (dict[str:DesiredWorkerLabel], optional): A dictionary of desired worker labels. Defaults to an empty dictionary.
92
- compute (Compute, optional): The compute configuration for the step. Hatchet Cloud only. Defaults to None.
93
-
94
- Returns:
95
- function: The decorated function with step metadata.
96
- """
75
+ rate_limits: list[RateLimit] | None = None,
76
+ desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
77
+ backoff_factor: float | None = None,
78
+ backoff_max_seconds: int | None = None,
79
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
97
80
  parents = parents or []
98
81
 
99
- def inner(func):
82
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
100
83
  limits = None
101
84
  if rate_limits:
102
85
  limits = [
@@ -104,18 +87,20 @@ def step(
104
87
  for rate_limit in rate_limits or []
105
88
  ]
106
89
 
107
- func._step_name = name.lower() or str(func.__name__).lower()
108
- func._step_parents = parents
109
- func._step_timeout = timeout
110
- func._step_retries = retries
111
- func._step_rate_limits = limits
112
- func._step_compute = compute
90
+ ## TODO: Use Protocol here to help with MyPy errors
91
+ func._step_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
92
+ func._step_parents = parents # type: ignore[attr-defined]
93
+ func._step_timeout = timeout # type: ignore[attr-defined]
94
+ func._step_retries = retries # type: ignore[attr-defined]
95
+ func._step_rate_limits = limits # type: ignore[attr-defined]
96
+ func._step_backoff_factor = backoff_factor # type: ignore[attr-defined]
97
+ func._step_backoff_max_seconds = backoff_max_seconds # type: ignore[attr-defined]
113
98
 
114
- func._step_desired_worker_labels = {}
99
+ func._step_desired_worker_labels = {} # type: ignore[attr-defined]
115
100
 
116
101
  for key, d in desired_worker_labels.items():
117
102
  value = d["value"] if "value" in d else None
118
- func._step_desired_worker_labels[key] = DesiredWorkerLabels(
103
+ func._step_desired_worker_labels[key] = DesiredWorkerLabels( # type: ignore[attr-defined]
119
104
  strValue=str(value) if not isinstance(value, int) else None,
120
105
  intValue=value if isinstance(value, int) else None,
121
106
  required=d["required"] if "required" in d else None,
@@ -132,9 +117,11 @@ def on_failure_step(
132
117
  name: str = "",
133
118
  timeout: str = "",
134
119
  retries: int = 0,
135
- rate_limits: List[RateLimit] | None = None,
136
- ):
137
- def inner(func):
120
+ rate_limits: list[RateLimit] | None = None,
121
+ backoff_factor: float | None = None,
122
+ backoff_max_seconds: int | None = None,
123
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
124
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
138
125
  limits = None
139
126
  if rate_limits:
140
127
  limits = [
@@ -142,10 +129,14 @@ def on_failure_step(
142
129
  for rate_limit in rate_limits or []
143
130
  ]
144
131
 
145
- func._on_failure_step_name = name.lower() or str(func.__name__).lower()
146
- func._on_failure_step_timeout = timeout
147
- func._on_failure_step_retries = retries
148
- func._on_failure_step_rate_limits = limits
132
+ ## TODO: Use Protocol here to help with MyPy errors
133
+ func._on_failure_step_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
134
+ func._on_failure_step_timeout = timeout # type: ignore[attr-defined]
135
+ func._on_failure_step_retries = retries # type: ignore[attr-defined]
136
+ func._on_failure_step_rate_limits = limits # type: ignore[attr-defined]
137
+ func._on_failure_step_backoff_factor = backoff_factor # type: ignore[attr-defined]
138
+ func._on_failure_step_backoff_max_seconds = backoff_max_seconds # type: ignore[attr-defined]
139
+
149
140
  return func
150
141
 
151
142
  return inner
@@ -155,11 +146,12 @@ def concurrency(
155
146
  name: str = "",
156
147
  max_runs: int = 1,
157
148
  limit_strategy: ConcurrencyLimitStrategy = ConcurrencyLimitStrategy.CANCEL_IN_PROGRESS,
158
- ):
159
- def inner(func):
160
- func._concurrency_fn_name = name.lower() or str(func.__name__).lower()
161
- func._concurrency_max_runs = max_runs
162
- func._concurrency_limit_strategy = limit_strategy
149
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
150
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
151
+ ## TODO: Use Protocol here to help with MyPy errors
152
+ func._concurrency_fn_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
153
+ func._concurrency_max_runs = max_runs # type: ignore[attr-defined]
154
+ func._concurrency_limit_strategy = limit_strategy # type: ignore[attr-defined]
163
155
 
164
156
  return func
165
157
 
@@ -180,8 +172,8 @@ class HatchetRest:
180
172
  rest: RestApi
181
173
 
182
174
  def __init__(self, config: ClientConfig = ClientConfig()):
183
- config: ClientConfig = ConfigLoader(".").load_client_config(config)
184
- self.rest = RestApi(config.server_url, config.token, config.tenant_id)
175
+ _config: ClientConfig = ConfigLoader(".").load_client_config(config)
176
+ self.rest = RestApi(_config.server_url, _config.token, _config.tenant_id)
185
177
 
186
178
 
187
179
  class Hatchet:
@@ -192,6 +184,8 @@ class Hatchet:
192
184
  for working with Hatchet workers, workflows, and steps.
193
185
 
194
186
  Attributes:
187
+ cron (CronClient): Interface for cron trigger operations.
188
+
195
189
  admin (AdminClient): Interface for administrative operations.
196
190
  dispatcher (DispatcherClient): Interface for dispatching operations.
197
191
  event (EventClient): Interface for event-related operations.
@@ -199,13 +193,17 @@ class Hatchet:
199
193
  """
200
194
 
201
195
  _client: Client
196
+ cron: CronClient
197
+ scheduled: ScheduledClient
202
198
 
203
199
  @classmethod
204
- def from_environment(cls, defaults: ClientConfig = ClientConfig(), **kwargs):
200
+ def from_environment(
201
+ cls, defaults: ClientConfig = ClientConfig(), **kwargs: Any
202
+ ) -> "Hatchet":
205
203
  return cls(client=new_client(defaults), **kwargs)
206
204
 
207
205
  @classmethod
208
- def from_config(cls, config: ClientConfig, **kwargs):
206
+ def from_config(cls, config: ClientConfig, **kwargs: Any) -> "Hatchet":
209
207
  return cls(client=new_client_raw(config), **kwargs)
210
208
 
211
209
  def __init__(
@@ -230,6 +228,9 @@ class Hatchet:
230
228
  if debug:
231
229
  logger.setLevel(logging.DEBUG)
232
230
 
231
+ self.cron = CronClient(self._client)
232
+ self.scheduled = ScheduledClient(self._client)
233
+
233
234
  @property
234
235
  @deprecated(
235
236
  "Direct access to client is deprecated and will be removed in a future version. Use specific client properties (Hatchet.admin, Hatchet.dispatcher, Hatchet.event, Hatchet.rest) instead. [0.32.0]",
@@ -238,31 +239,31 @@ class Hatchet:
238
239
  return self._client
239
240
 
240
241
  @property
241
- def admin(self):
242
+ def admin(self) -> AdminClient:
242
243
  return self._client.admin
243
244
 
244
245
  @property
245
- def dispatcher(self):
246
+ def dispatcher(self) -> DispatcherClient:
246
247
  return self._client.dispatcher
247
248
 
248
249
  @property
249
- def event(self):
250
+ def event(self) -> EventClient:
250
251
  return self._client.event
251
252
 
252
253
  @property
253
- def rest(self):
254
+ def rest(self) -> RestApi:
254
255
  return self._client.rest
255
256
 
256
257
  @property
257
- def listener(self):
258
+ def listener(self) -> RunEventListenerClient:
258
259
  return self._client.listener
259
260
 
260
261
  @property
261
- def config(self):
262
+ def config(self) -> ClientConfig:
262
263
  return self._client.config
263
264
 
264
265
  @property
265
- def tenant_id(self):
266
+ def tenant_id(self) -> str:
266
267
  return self._client.config.tenant_id
267
268
 
268
269
  concurrency = staticmethod(concurrency)
@@ -275,7 +276,7 @@ class Hatchet:
275
276
 
276
277
  def worker(
277
278
  self, name: str, max_runs: int | None = None, labels: dict[str, str | int] = {}
278
- ):
279
+ ) -> Worker:
279
280
  try:
280
281
  loop = asyncio.get_running_loop()
281
282
  except RuntimeError:
hatchet_sdk/loader.py CHANGED
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import os
2
3
  from logging import Logger, getLogger
3
4
  from typing import Dict, Optional
@@ -38,9 +39,10 @@ class ClientConfig:
38
39
  logger: Logger = None,
39
40
  grpc_max_recv_message_length: int = 4 * 1024 * 1024, # 4MB
40
41
  grpc_max_send_message_length: int = 4 * 1024 * 1024, # 4MB
41
- runnable_actions: list[
42
- str
43
- ] = None, # list of action names that are runnable, defaults to all actions
42
+ otel_exporter_oltp_endpoint: str | None = None,
43
+ otel_service_name: str | None = None,
44
+ otel_exporter_oltp_headers: dict[str, str] | None = None,
45
+ otel_exporter_oltp_protocol: str | None = None,
44
46
  ):
45
47
  self.tenant_id = tenant_id
46
48
  self.tls_config = tls_config
@@ -51,6 +53,10 @@ class ClientConfig:
51
53
  self.logInterceptor = logger
52
54
  self.grpc_max_recv_message_length = grpc_max_recv_message_length
53
55
  self.grpc_max_send_message_length = grpc_max_send_message_length
56
+ self.otel_exporter_oltp_endpoint = otel_exporter_oltp_endpoint
57
+ self.otel_service_name = otel_service_name
58
+ self.otel_exporter_oltp_headers = otel_exporter_oltp_headers
59
+ self.otel_exporter_oltp_protocol = otel_exporter_oltp_protocol
54
60
 
55
61
  if not self.logInterceptor:
56
62
  self.logInterceptor = getLogger()
@@ -65,12 +71,6 @@ class ClientConfig:
65
71
 
66
72
  self.listener_v2_timeout = listener_v2_timeout
67
73
 
68
- self.runnable_actions: list[str] | None = (
69
- [self.namespace + action for action in runnable_actions]
70
- if runnable_actions
71
- else None
72
- )
73
-
74
74
 
75
75
  class ConfigLoader:
76
76
  def __init__(self, directory: str):
@@ -136,11 +136,31 @@ class ConfigLoader:
136
136
 
137
137
  tls_config = self._load_tls_config(config_data["tls"], host_port)
138
138
 
139
- raw_runnable_actions = get_config_value(
140
- "runnable_actions", "HATCHET_CLOUD_ACTIONS"
139
+ otel_exporter_oltp_endpoint = get_config_value(
140
+ "otel_exporter_oltp_endpoint", "HATCHET_CLIENT_OTEL_EXPORTER_OTLP_ENDPOINT"
141
+ )
142
+
143
+ otel_service_name = get_config_value(
144
+ "otel_service_name", "HATCHET_CLIENT_OTEL_SERVICE_NAME"
141
145
  )
142
- runnable_actions = (
143
- raw_runnable_actions.split(",") if raw_runnable_actions else None
146
+
147
+ _oltp_headers = get_config_value(
148
+ "otel_exporter_oltp_headers", "HATCHET_CLIENT_OTEL_EXPORTER_OTLP_HEADERS"
149
+ )
150
+
151
+ if _oltp_headers:
152
+ try:
153
+ otel_header_key, api_key = _oltp_headers.split("=", maxsplit=1)
154
+ otel_exporter_oltp_headers = {otel_header_key: api_key}
155
+ except ValueError:
156
+ raise ValueError(
157
+ "HATCHET_CLIENT_OTEL_EXPORTER_OTLP_HEADERS must be in the format `key=value`"
158
+ )
159
+ else:
160
+ otel_exporter_oltp_headers = None
161
+
162
+ otel_exporter_oltp_protocol = get_config_value(
163
+ "otel_exporter_oltp_protocol", "HATCHET_CLIENT_OTEL_EXPORTER_OTLP_PROTOCOL"
144
164
  )
145
165
 
146
166
  return ClientConfig(
@@ -154,7 +174,10 @@ class ConfigLoader:
154
174
  logger=defaults.logInterceptor,
155
175
  grpc_max_recv_message_length=grpc_max_recv_message_length,
156
176
  grpc_max_send_message_length=grpc_max_send_message_length,
157
- runnable_actions=runnable_actions,
177
+ otel_exporter_oltp_endpoint=otel_exporter_oltp_endpoint,
178
+ otel_service_name=otel_service_name,
179
+ otel_exporter_oltp_headers=otel_exporter_oltp_headers,
180
+ otel_exporter_oltp_protocol=otel_exporter_oltp_protocol,
158
181
  )
159
182
 
160
183
  def _load_tls_config(self, tls_data: Dict, host_port) -> ClientTLSConfig:
@@ -0,0 +1,15 @@
1
+ from typing import Any
2
+
3
+
4
+ def flatten(xs: dict[str, Any], parent_key: str, separator: str) -> dict[str, Any]:
5
+ items = []
6
+
7
+ for k, v in xs.items():
8
+ new_key = parent_key + separator + k if parent_key else k
9
+
10
+ if isinstance(v, dict):
11
+ items.extend(flatten(v, new_key, separator).items())
12
+ else:
13
+ items.append((new_key, v))
14
+
15
+ return dict(items)