hatchet-sdk 0.40.0a8__py3-none-any.whl → 0.41.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 (149) 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.pyi +2 -0
  73. hatchet_sdk/contracts/events_pb2.pyi +2 -0
  74. hatchet_sdk/contracts/workflows_pb2.pyi +2 -0
  75. hatchet_sdk/features/cron.py +286 -0
  76. hatchet_sdk/features/scheduled.py +248 -0
  77. hatchet_sdk/hatchet.py +71 -79
  78. hatchet_sdk/loader.py +37 -14
  79. hatchet_sdk/utils/serialization.py +15 -0
  80. hatchet_sdk/utils/tracing.py +67 -0
  81. hatchet_sdk/worker/runner/runner.py +158 -112
  82. hatchet_sdk/worker/worker.py +1 -17
  83. {hatchet_sdk-0.40.0a8.dist-info → hatchet_sdk-0.41.0.dist-info}/METADATA +8 -2
  84. {hatchet_sdk-0.40.0a8.dist-info → hatchet_sdk-0.41.0.dist-info}/RECORD +86 -140
  85. {hatchet_sdk-0.40.0a8.dist-info → hatchet_sdk-0.41.0.dist-info}/entry_points.txt +0 -1
  86. hatchet_sdk/clients/cloud_rest/__init__.py +0 -186
  87. hatchet_sdk/clients/cloud_rest/api/__init__.py +0 -14
  88. hatchet_sdk/clients/cloud_rest/api/billing_api.py +0 -819
  89. hatchet_sdk/clients/cloud_rest/api/build_api.py +0 -298
  90. hatchet_sdk/clients/cloud_rest/api/feature_flags_api.py +0 -295
  91. hatchet_sdk/clients/cloud_rest/api/github_api.py +0 -1347
  92. hatchet_sdk/clients/cloud_rest/api/log_api.py +0 -971
  93. hatchet_sdk/clients/cloud_rest/api/managed_worker_api.py +0 -2546
  94. hatchet_sdk/clients/cloud_rest/api/metadata_api.py +0 -265
  95. hatchet_sdk/clients/cloud_rest/api/metrics_api.py +0 -1026
  96. hatchet_sdk/clients/cloud_rest/api/tenant_api.py +0 -301
  97. hatchet_sdk/clients/cloud_rest/api/user_api.py +0 -473
  98. hatchet_sdk/clients/cloud_rest/api/workflow_api.py +0 -369
  99. hatchet_sdk/clients/cloud_rest/api_client.py +0 -727
  100. hatchet_sdk/clients/cloud_rest/api_response.py +0 -22
  101. hatchet_sdk/clients/cloud_rest/configuration.py +0 -488
  102. hatchet_sdk/clients/cloud_rest/exceptions.py +0 -200
  103. hatchet_sdk/clients/cloud_rest/models/__init__.py +0 -157
  104. hatchet_sdk/clients/cloud_rest/models/billing_portal_link_get200_response.py +0 -85
  105. hatchet_sdk/clients/cloud_rest/models/build_get200_response.py +0 -121
  106. hatchet_sdk/clients/cloud_rest/models/github_app_list_branches200_response_inner.py +0 -86
  107. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response.py +0 -119
  108. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_pagination.py +0 -95
  109. hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_rows_inner_metadata.py +0 -98
  110. hatchet_sdk/clients/cloud_rest/models/github_app_list_repos200_response_inner.py +0 -86
  111. hatchet_sdk/clients/cloud_rest/models/infra_as_code_create_request.py +0 -107
  112. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner.py +0 -136
  113. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_event.py +0 -83
  114. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly.py +0 -100
  115. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly_app.py +0 -86
  116. hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_log.py +0 -83
  117. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request.py +0 -128
  118. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_build_config.py +0 -121
  119. hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_runtime_config.py +0 -166
  120. hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response.py +0 -119
  121. hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response_rows_inner.py +0 -117
  122. hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response.py +0 -119
  123. hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response_rows_inner.py +0 -113
  124. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner.py +0 -154
  125. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config.py +0 -151
  126. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config_steps_inner.py +0 -109
  127. hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_runtime_configs_inner.py +0 -171
  128. hatchet_sdk/clients/cloud_rest/models/managed_worker_update_request.py +0 -131
  129. hatchet_sdk/clients/cloud_rest/models/metadata_get200_response.py +0 -101
  130. hatchet_sdk/clients/cloud_rest/models/metadata_get400_response.py +0 -105
  131. hatchet_sdk/clients/cloud_rest/models/metadata_get400_response_errors_inner.py +0 -102
  132. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner.py +0 -108
  133. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner.py +0 -102
  134. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram.py +0 -113
  135. hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram_buckets_inner.py +0 -93
  136. hatchet_sdk/clients/cloud_rest/models/runtime_config_list_actions200_response.py +0 -83
  137. hatchet_sdk/clients/cloud_rest/models/subscription_upsert200_response.py +0 -114
  138. hatchet_sdk/clients/cloud_rest/models/subscription_upsert_request.py +0 -88
  139. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response.py +0 -170
  140. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_coupons_inner.py +0 -137
  141. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_plans_inner.py +0 -103
  142. hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_subscription.py +0 -114
  143. hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response.py +0 -107
  144. hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response_results_inner.py +0 -105
  145. hatchet_sdk/clients/cloud_rest/rest.py +0 -182
  146. hatchet_sdk/compute/__init__.py +0 -0
  147. hatchet_sdk/compute/configs.py +0 -34
  148. hatchet_sdk/compute/managed_compute.py +0 -111
  149. {hatchet_sdk-0.40.0a8.dist-info → hatchet_sdk-0.41.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,14 @@ 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
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
97
78
  parents = parents or []
98
79
 
99
- def inner(func):
80
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
100
81
  limits = None
101
82
  if rate_limits:
102
83
  limits = [
@@ -104,18 +85,18 @@ def step(
104
85
  for rate_limit in rate_limits or []
105
86
  ]
106
87
 
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
88
+ ## TODO: Use Protocol here to help with MyPy errors
89
+ func._step_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
90
+ func._step_parents = parents # type: ignore[attr-defined]
91
+ func._step_timeout = timeout # type: ignore[attr-defined]
92
+ func._step_retries = retries # type: ignore[attr-defined]
93
+ func._step_rate_limits = limits # type: ignore[attr-defined]
113
94
 
114
- func._step_desired_worker_labels = {}
95
+ func._step_desired_worker_labels = {} # type: ignore[attr-defined]
115
96
 
116
97
  for key, d in desired_worker_labels.items():
117
98
  value = d["value"] if "value" in d else None
118
- func._step_desired_worker_labels[key] = DesiredWorkerLabels(
99
+ func._step_desired_worker_labels[key] = DesiredWorkerLabels( # type: ignore[attr-defined]
119
100
  strValue=str(value) if not isinstance(value, int) else None,
120
101
  intValue=value if isinstance(value, int) else None,
121
102
  required=d["required"] if "required" in d else None,
@@ -132,9 +113,9 @@ def on_failure_step(
132
113
  name: str = "",
133
114
  timeout: str = "",
134
115
  retries: int = 0,
135
- rate_limits: List[RateLimit] | None = None,
136
- ):
137
- def inner(func):
116
+ rate_limits: list[RateLimit] | None = None,
117
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
118
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
138
119
  limits = None
139
120
  if rate_limits:
140
121
  limits = [
@@ -142,10 +123,11 @@ def on_failure_step(
142
123
  for rate_limit in rate_limits or []
143
124
  ]
144
125
 
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
126
+ ## TODO: Use Protocol here to help with MyPy errors
127
+ func._on_failure_step_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
128
+ func._on_failure_step_timeout = timeout # type: ignore[attr-defined]
129
+ func._on_failure_step_retries = retries # type: ignore[attr-defined]
130
+ func._on_failure_step_rate_limits = limits # type: ignore[attr-defined]
149
131
  return func
150
132
 
151
133
  return inner
@@ -155,11 +137,12 @@ def concurrency(
155
137
  name: str = "",
156
138
  max_runs: int = 1,
157
139
  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
140
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
141
+ def inner(func: Callable[P, R]) -> Callable[P, R]:
142
+ ## TODO: Use Protocol here to help with MyPy errors
143
+ func._concurrency_fn_name = name.lower() or str(func.__name__).lower() # type: ignore[attr-defined]
144
+ func._concurrency_max_runs = max_runs # type: ignore[attr-defined]
145
+ func._concurrency_limit_strategy = limit_strategy # type: ignore[attr-defined]
163
146
 
164
147
  return func
165
148
 
@@ -180,8 +163,8 @@ class HatchetRest:
180
163
  rest: RestApi
181
164
 
182
165
  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)
166
+ _config: ClientConfig = ConfigLoader(".").load_client_config(config)
167
+ self.rest = RestApi(_config.server_url, _config.token, _config.tenant_id)
185
168
 
186
169
 
187
170
  class Hatchet:
@@ -192,6 +175,8 @@ class Hatchet:
192
175
  for working with Hatchet workers, workflows, and steps.
193
176
 
194
177
  Attributes:
178
+ cron (CronClient): Interface for cron trigger operations.
179
+
195
180
  admin (AdminClient): Interface for administrative operations.
196
181
  dispatcher (DispatcherClient): Interface for dispatching operations.
197
182
  event (EventClient): Interface for event-related operations.
@@ -199,13 +184,17 @@ class Hatchet:
199
184
  """
200
185
 
201
186
  _client: Client
187
+ cron: CronClient
188
+ scheduled: ScheduledClient
202
189
 
203
190
  @classmethod
204
- def from_environment(cls, defaults: ClientConfig = ClientConfig(), **kwargs):
191
+ def from_environment(
192
+ cls, defaults: ClientConfig = ClientConfig(), **kwargs: Any
193
+ ) -> "Hatchet":
205
194
  return cls(client=new_client(defaults), **kwargs)
206
195
 
207
196
  @classmethod
208
- def from_config(cls, config: ClientConfig, **kwargs):
197
+ def from_config(cls, config: ClientConfig, **kwargs: Any) -> "Hatchet":
209
198
  return cls(client=new_client_raw(config), **kwargs)
210
199
 
211
200
  def __init__(
@@ -230,6 +219,9 @@ class Hatchet:
230
219
  if debug:
231
220
  logger.setLevel(logging.DEBUG)
232
221
 
222
+ self.cron = CronClient(self._client)
223
+ self.scheduled = ScheduledClient(self._client)
224
+
233
225
  @property
234
226
  @deprecated(
235
227
  "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 +230,31 @@ class Hatchet:
238
230
  return self._client
239
231
 
240
232
  @property
241
- def admin(self):
233
+ def admin(self) -> AdminClient:
242
234
  return self._client.admin
243
235
 
244
236
  @property
245
- def dispatcher(self):
237
+ def dispatcher(self) -> DispatcherClient:
246
238
  return self._client.dispatcher
247
239
 
248
240
  @property
249
- def event(self):
241
+ def event(self) -> EventClient:
250
242
  return self._client.event
251
243
 
252
244
  @property
253
- def rest(self):
245
+ def rest(self) -> RestApi:
254
246
  return self._client.rest
255
247
 
256
248
  @property
257
- def listener(self):
249
+ def listener(self) -> RunEventListenerClient:
258
250
  return self._client.listener
259
251
 
260
252
  @property
261
- def config(self):
253
+ def config(self) -> ClientConfig:
262
254
  return self._client.config
263
255
 
264
256
  @property
265
- def tenant_id(self):
257
+ def tenant_id(self) -> str:
266
258
  return self._client.config.tenant_id
267
259
 
268
260
  concurrency = staticmethod(concurrency)
@@ -275,7 +267,7 @@ class Hatchet:
275
267
 
276
268
  def worker(
277
269
  self, name: str, max_runs: int | None = None, labels: dict[str, str | int] = {}
278
- ):
270
+ ) -> Worker:
279
271
  try:
280
272
  loop = asyncio.get_running_loop()
281
273
  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)