hatchet-sdk 0.40.0a9__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.
- hatchet_sdk/clients/admin.py +129 -59
- hatchet_sdk/clients/dispatcher/action_listener.py +25 -2
- hatchet_sdk/clients/events.py +91 -52
- hatchet_sdk/clients/rest/__init__.py +21 -0
- hatchet_sdk/clients/rest/api/api_token_api.py +12 -9
- hatchet_sdk/clients/rest/api/default_api.py +24 -18
- hatchet_sdk/clients/rest/api/event_api.py +32 -24
- hatchet_sdk/clients/rest/api/github_api.py +4 -3
- hatchet_sdk/clients/rest/api/log_api.py +4 -3
- hatchet_sdk/clients/rest/api/metadata_api.py +12 -9
- hatchet_sdk/clients/rest/api/rate_limits_api.py +7 -4
- hatchet_sdk/clients/rest/api/slack_api.py +8 -6
- hatchet_sdk/clients/rest/api/sns_api.py +12 -9
- hatchet_sdk/clients/rest/api/step_run_api.py +28 -21
- hatchet_sdk/clients/rest/api/tenant_api.py +67 -49
- hatchet_sdk/clients/rest/api/user_api.py +24 -18
- hatchet_sdk/clients/rest/api/worker_api.py +12 -9
- hatchet_sdk/clients/rest/api/workflow_api.py +3073 -936
- hatchet_sdk/clients/rest/api/workflow_run_api.py +669 -21
- hatchet_sdk/clients/rest/api_client.py +34 -11
- hatchet_sdk/clients/rest/configuration.py +161 -36
- hatchet_sdk/clients/rest/models/__init__.py +21 -0
- hatchet_sdk/clients/rest/models/api_errors.py +3 -3
- hatchet_sdk/clients/rest/models/bulk_create_event_request.py +3 -3
- hatchet_sdk/clients/rest/models/bulk_create_event_response.py +3 -3
- 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
- hatchet_sdk/clients/{cloud_rest/models/github_app_list_installations200_response_rows_inner.py → rest/models/cron_workflows.py} +54 -21
- hatchet_sdk/clients/{cloud_rest/models/log_list200_response.py → rest/models/cron_workflows_list.py} +13 -22
- hatchet_sdk/clients/rest/models/cron_workflows_order_by_field.py +37 -0
- hatchet_sdk/clients/rest/models/event_list.py +3 -3
- hatchet_sdk/clients/rest/models/get_step_run_diff_response.py +3 -3
- hatchet_sdk/clients/rest/models/job.py +3 -3
- hatchet_sdk/clients/rest/models/job_run.py +3 -3
- hatchet_sdk/clients/rest/models/list_api_tokens_response.py +3 -3
- hatchet_sdk/clients/rest/models/list_pull_requests_response.py +3 -3
- hatchet_sdk/clients/rest/models/list_slack_webhooks.py +3 -3
- hatchet_sdk/clients/rest/models/list_sns_integrations.py +3 -3
- hatchet_sdk/clients/rest/models/log_line_list.py +3 -3
- hatchet_sdk/clients/rest/models/rate_limit_list.py +3 -3
- hatchet_sdk/clients/rest/models/replay_workflow_runs_response.py +3 -3
- hatchet_sdk/clients/{cloud_rest/models/log_list200_response_rows_inner.py → rest/models/schedule_workflow_run_request.py} +12 -12
- hatchet_sdk/clients/rest/models/scheduled_run_status.py +42 -0
- hatchet_sdk/clients/rest/models/scheduled_workflows.py +153 -0
- hatchet_sdk/clients/{cloud_rest/models/managed_worker_list200_response.py → rest/models/scheduled_workflows_list.py} +13 -22
- hatchet_sdk/clients/rest/models/scheduled_workflows_order_by_field.py +37 -0
- hatchet_sdk/clients/rest/models/step_run_archive_list.py +3 -3
- hatchet_sdk/clients/rest/models/step_run_event_list.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_alert_email_group_list.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_invite_list.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_list.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_member_list.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_queue_metrics.py +16 -0
- hatchet_sdk/clients/rest/models/tenant_resource_policy.py +3 -3
- hatchet_sdk/clients/rest/models/tenant_step_run_queue_metrics.py +1 -1
- hatchet_sdk/clients/rest/models/user_tenant_memberships_list.py +3 -3
- hatchet_sdk/clients/rest/models/webhook_worker_list_response.py +3 -3
- hatchet_sdk/clients/rest/models/webhook_worker_request_list_response.py +3 -3
- hatchet_sdk/clients/rest/models/worker.py +20 -9
- hatchet_sdk/clients/rest/models/worker_list.py +3 -3
- hatchet_sdk/clients/{cloud_rest/models/tenant_billing_state_get200_response_payment_methods_inner.py → rest/models/worker_runtime_info.py} +23 -19
- hatchet_sdk/clients/rest/models/worker_runtime_sdks.py +38 -0
- hatchet_sdk/clients/rest/models/workflow.py +9 -9
- hatchet_sdk/clients/rest/models/workflow_list.py +3 -3
- hatchet_sdk/clients/rest/models/workflow_run.py +3 -3
- hatchet_sdk/clients/rest/models/workflow_run_list.py +3 -3
- hatchet_sdk/clients/rest/models/workflow_run_shape.py +3 -3
- hatchet_sdk/clients/rest/models/workflow_runs_metrics.py +1 -5
- hatchet_sdk/clients/rest/models/workflow_triggers.py +6 -6
- hatchet_sdk/clients/rest/models/workflow_version.py +3 -3
- hatchet_sdk/clients/rest/rest.py +3 -3
- hatchet_sdk/clients/rest_client.py +200 -21
- hatchet_sdk/contracts/dispatcher_pb2.pyi +2 -0
- hatchet_sdk/contracts/events_pb2.pyi +2 -0
- hatchet_sdk/contracts/workflows_pb2.pyi +2 -0
- hatchet_sdk/features/cron.py +286 -0
- hatchet_sdk/features/scheduled.py +248 -0
- hatchet_sdk/hatchet.py +71 -79
- hatchet_sdk/loader.py +37 -14
- hatchet_sdk/utils/serialization.py +15 -0
- hatchet_sdk/utils/tracing.py +67 -0
- hatchet_sdk/worker/runner/runner.py +158 -112
- hatchet_sdk/worker/worker.py +1 -17
- {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.41.0.dist-info}/METADATA +8 -2
- {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.41.0.dist-info}/RECORD +86 -140
- {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.41.0.dist-info}/entry_points.txt +0 -1
- hatchet_sdk/clients/cloud_rest/__init__.py +0 -186
- hatchet_sdk/clients/cloud_rest/api/__init__.py +0 -14
- hatchet_sdk/clients/cloud_rest/api/billing_api.py +0 -819
- hatchet_sdk/clients/cloud_rest/api/build_api.py +0 -298
- hatchet_sdk/clients/cloud_rest/api/feature_flags_api.py +0 -295
- hatchet_sdk/clients/cloud_rest/api/github_api.py +0 -1347
- hatchet_sdk/clients/cloud_rest/api/log_api.py +0 -971
- hatchet_sdk/clients/cloud_rest/api/managed_worker_api.py +0 -2546
- hatchet_sdk/clients/cloud_rest/api/metadata_api.py +0 -265
- hatchet_sdk/clients/cloud_rest/api/metrics_api.py +0 -1026
- hatchet_sdk/clients/cloud_rest/api/tenant_api.py +0 -301
- hatchet_sdk/clients/cloud_rest/api/user_api.py +0 -473
- hatchet_sdk/clients/cloud_rest/api/workflow_api.py +0 -369
- hatchet_sdk/clients/cloud_rest/api_client.py +0 -727
- hatchet_sdk/clients/cloud_rest/api_response.py +0 -22
- hatchet_sdk/clients/cloud_rest/configuration.py +0 -488
- hatchet_sdk/clients/cloud_rest/exceptions.py +0 -200
- hatchet_sdk/clients/cloud_rest/models/__init__.py +0 -157
- hatchet_sdk/clients/cloud_rest/models/billing_portal_link_get200_response.py +0 -85
- hatchet_sdk/clients/cloud_rest/models/build_get200_response.py +0 -121
- hatchet_sdk/clients/cloud_rest/models/github_app_list_branches200_response_inner.py +0 -86
- hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response.py +0 -119
- hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_pagination.py +0 -95
- hatchet_sdk/clients/cloud_rest/models/github_app_list_installations200_response_rows_inner_metadata.py +0 -98
- hatchet_sdk/clients/cloud_rest/models/github_app_list_repos200_response_inner.py +0 -86
- hatchet_sdk/clients/cloud_rest/models/infra_as_code_create_request.py +0 -107
- hatchet_sdk/clients/cloud_rest/models/log_create_request_inner.py +0 -136
- hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_event.py +0 -83
- hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly.py +0 -100
- hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_fly_app.py +0 -86
- hatchet_sdk/clients/cloud_rest/models/log_create_request_inner_log.py +0 -83
- hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request.py +0 -128
- hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_build_config.py +0 -121
- hatchet_sdk/clients/cloud_rest/models/managed_worker_create_request_runtime_config.py +0 -166
- hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response.py +0 -119
- hatchet_sdk/clients/cloud_rest/models/managed_worker_events_list200_response_rows_inner.py +0 -117
- hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response.py +0 -119
- hatchet_sdk/clients/cloud_rest/models/managed_worker_instances_list200_response_rows_inner.py +0 -113
- hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner.py +0 -154
- hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config.py +0 -151
- hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_build_config_steps_inner.py +0 -109
- hatchet_sdk/clients/cloud_rest/models/managed_worker_list200_response_rows_inner_runtime_configs_inner.py +0 -171
- hatchet_sdk/clients/cloud_rest/models/managed_worker_update_request.py +0 -131
- hatchet_sdk/clients/cloud_rest/models/metadata_get200_response.py +0 -101
- hatchet_sdk/clients/cloud_rest/models/metadata_get400_response.py +0 -105
- hatchet_sdk/clients/cloud_rest/models/metadata_get400_response_errors_inner.py +0 -102
- hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner.py +0 -108
- hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner.py +0 -102
- hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram.py +0 -113
- hatchet_sdk/clients/cloud_rest/models/metrics_cpu_get200_response_inner_histograms_inner_histogram_buckets_inner.py +0 -93
- hatchet_sdk/clients/cloud_rest/models/runtime_config_list_actions200_response.py +0 -83
- hatchet_sdk/clients/cloud_rest/models/subscription_upsert200_response.py +0 -114
- hatchet_sdk/clients/cloud_rest/models/subscription_upsert_request.py +0 -88
- hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response.py +0 -170
- hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_coupons_inner.py +0 -137
- hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_plans_inner.py +0 -103
- hatchet_sdk/clients/cloud_rest/models/tenant_billing_state_get200_response_subscription.py +0 -114
- hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response.py +0 -107
- hatchet_sdk/clients/cloud_rest/models/workflow_run_events_get_metrics200_response_results_inner.py +0 -105
- hatchet_sdk/clients/cloud_rest/rest.py +0 -182
- hatchet_sdk/compute/__init__.py +0 -0
- hatchet_sdk/compute/configs.py +0 -34
- hatchet_sdk/compute/managed_compute.py +0 -111
- {hatchet_sdk-0.40.0a9.dist-info → hatchet_sdk-0.41.0.dist-info}/WHEEL +0 -0
hatchet_sdk/clients/admin.py
CHANGED
|
@@ -23,6 +23,13 @@ from hatchet_sdk.contracts.workflows_pb2 import (
|
|
|
23
23
|
WorkflowVersion,
|
|
24
24
|
)
|
|
25
25
|
from hatchet_sdk.contracts.workflows_pb2_grpc import WorkflowServiceStub
|
|
26
|
+
from hatchet_sdk.utils.serialization import flatten
|
|
27
|
+
from hatchet_sdk.utils.tracing import (
|
|
28
|
+
create_carrier,
|
|
29
|
+
create_tracer,
|
|
30
|
+
inject_carrier_into_metadata,
|
|
31
|
+
parse_carrier_from_metadata,
|
|
32
|
+
)
|
|
26
33
|
from hatchet_sdk.workflow_run import RunRef, WorkflowRunRef
|
|
27
34
|
|
|
28
35
|
from ..loader import ClientConfig
|
|
@@ -164,6 +171,7 @@ class AdminClientAioImpl(AdminClientBase):
|
|
|
164
171
|
self.token = config.token
|
|
165
172
|
self.listener_client = new_listener(config)
|
|
166
173
|
self.namespace = config.namespace
|
|
174
|
+
self.otel_tracer = create_tracer(config=config)
|
|
167
175
|
|
|
168
176
|
async def run(
|
|
169
177
|
self,
|
|
@@ -186,44 +194,74 @@ class AdminClientAioImpl(AdminClientBase):
|
|
|
186
194
|
async def run_workflow(
|
|
187
195
|
self, workflow_name: str, input: any, options: TriggerWorkflowOptions = None
|
|
188
196
|
) -> WorkflowRunRef:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
197
|
+
ctx = parse_carrier_from_metadata(
|
|
198
|
+
(options or {}).get("additional_metadata", {})
|
|
199
|
+
)
|
|
192
200
|
|
|
193
|
-
|
|
201
|
+
with self.otel_tracer.start_as_current_span(
|
|
202
|
+
f"hatchet.async_run_workflow.{workflow_name}", context=ctx
|
|
203
|
+
) as span:
|
|
204
|
+
carrier = create_carrier()
|
|
194
205
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
namespace = options["namespace"]
|
|
201
|
-
del options["namespace"]
|
|
206
|
+
try:
|
|
207
|
+
if not self.pooled_workflow_listener:
|
|
208
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(
|
|
209
|
+
self.config
|
|
210
|
+
)
|
|
202
211
|
|
|
203
|
-
|
|
204
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
212
|
+
namespace = self.namespace
|
|
205
213
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
workflow_run_id=resp.workflow_run_id,
|
|
213
|
-
workflow_listener=self.pooled_workflow_listener,
|
|
214
|
-
workflow_run_event_listener=self.listener_client,
|
|
215
|
-
)
|
|
216
|
-
except grpc.RpcError as e:
|
|
217
|
-
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
218
|
-
raise DedupeViolationErr(e.details())
|
|
214
|
+
if (
|
|
215
|
+
options is not None
|
|
216
|
+
and "namespace" in options
|
|
217
|
+
and options["namespace"] is not None
|
|
218
|
+
):
|
|
219
|
+
namespace = options.pop("namespace")
|
|
219
220
|
|
|
220
|
-
|
|
221
|
+
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
222
|
+
workflow_name = f"{namespace}{workflow_name}"
|
|
223
|
+
|
|
224
|
+
if options is not None and "additional_metadata" in options:
|
|
225
|
+
options["additional_metadata"] = inject_carrier_into_metadata(
|
|
226
|
+
options["additional_metadata"], carrier
|
|
227
|
+
)
|
|
228
|
+
span.set_attributes(
|
|
229
|
+
flatten(
|
|
230
|
+
options["additional_metadata"], parent_key="", separator="."
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
request = self._prepare_workflow_request(workflow_name, input, options)
|
|
235
|
+
|
|
236
|
+
span.add_event(
|
|
237
|
+
"Triggering workflow", attributes={"workflow_name": workflow_name}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
resp: TriggerWorkflowResponse = await self.aio_client.TriggerWorkflow(
|
|
241
|
+
request,
|
|
242
|
+
metadata=get_metadata(self.token),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
span.add_event(
|
|
246
|
+
"Received workflow response",
|
|
247
|
+
attributes={"workflow_name": workflow_name},
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
return WorkflowRunRef(
|
|
251
|
+
workflow_run_id=resp.workflow_run_id,
|
|
252
|
+
workflow_listener=self.pooled_workflow_listener,
|
|
253
|
+
workflow_run_event_listener=self.listener_client,
|
|
254
|
+
)
|
|
255
|
+
except grpc.RpcError as e:
|
|
256
|
+
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
257
|
+
raise DedupeViolationErr(e.details())
|
|
258
|
+
|
|
259
|
+
raise ValueError(f"gRPC error: {e}")
|
|
221
260
|
|
|
222
261
|
@tenacity_retry
|
|
223
262
|
async def run_workflows(
|
|
224
263
|
self, workflows: List[WorkflowRunDict], options: TriggerWorkflowOptions = None
|
|
225
264
|
) -> List[WorkflowRunRef]:
|
|
226
|
-
|
|
227
265
|
if len(workflows) == 0:
|
|
228
266
|
raise ValueError("No workflows to run")
|
|
229
267
|
try:
|
|
@@ -243,7 +281,6 @@ class AdminClientAioImpl(AdminClientBase):
|
|
|
243
281
|
workflow_run_requests: TriggerWorkflowRequest = []
|
|
244
282
|
|
|
245
283
|
for workflow in workflows:
|
|
246
|
-
|
|
247
284
|
workflow_name = workflow["workflow_name"]
|
|
248
285
|
input_data = workflow["input"]
|
|
249
286
|
options = workflow["options"]
|
|
@@ -360,6 +397,7 @@ class AdminClient(AdminClientBase):
|
|
|
360
397
|
self.token = config.token
|
|
361
398
|
self.listener_client = new_listener(config)
|
|
362
399
|
self.namespace = config.namespace
|
|
400
|
+
self.otel_tracer = create_tracer(config=config)
|
|
363
401
|
|
|
364
402
|
@tenacity_retry
|
|
365
403
|
def put_workflow(
|
|
@@ -408,7 +446,6 @@ class AdminClient(AdminClientBase):
|
|
|
408
446
|
options: ScheduleTriggerWorkflowOptions = None,
|
|
409
447
|
) -> WorkflowVersion:
|
|
410
448
|
try:
|
|
411
|
-
|
|
412
449
|
namespace = self.namespace
|
|
413
450
|
|
|
414
451
|
if (
|
|
@@ -436,55 +473,88 @@ class AdminClient(AdminClientBase):
|
|
|
436
473
|
|
|
437
474
|
raise ValueError(f"gRPC error: {e}")
|
|
438
475
|
|
|
476
|
+
## TODO: `options` is treated as a dict (wrong type hint)
|
|
477
|
+
## TODO: `any` type hint should come from `typing`
|
|
439
478
|
@tenacity_retry
|
|
440
479
|
def run_workflow(
|
|
441
480
|
self, workflow_name: str, input: any, options: TriggerWorkflowOptions = None
|
|
442
481
|
) -> WorkflowRunRef:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
482
|
+
ctx = parse_carrier_from_metadata(
|
|
483
|
+
(options or {}).get("additional_metadata", {})
|
|
484
|
+
)
|
|
446
485
|
|
|
447
|
-
|
|
486
|
+
with self.otel_tracer.start_as_current_span(
|
|
487
|
+
f"hatchet.run_workflow.{workflow_name}", context=ctx
|
|
488
|
+
) as span:
|
|
489
|
+
carrier = create_carrier()
|
|
448
490
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
namespace = options["namespace"]
|
|
455
|
-
del options["namespace"]
|
|
491
|
+
try:
|
|
492
|
+
if not self.pooled_workflow_listener:
|
|
493
|
+
self.pooled_workflow_listener = PooledWorkflowRunListener(
|
|
494
|
+
self.config
|
|
495
|
+
)
|
|
456
496
|
|
|
457
|
-
|
|
458
|
-
workflow_name = f"{namespace}{workflow_name}"
|
|
497
|
+
namespace = self.namespace
|
|
459
498
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
workflow_listener=self.pooled_workflow_listener,
|
|
468
|
-
workflow_run_event_listener=self.listener_client,
|
|
469
|
-
)
|
|
470
|
-
except grpc.RpcError as e:
|
|
471
|
-
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
472
|
-
raise DedupeViolationErr(e.details())
|
|
499
|
+
## TODO: Factor this out - it's repeated a lot of places
|
|
500
|
+
if (
|
|
501
|
+
options is not None
|
|
502
|
+
and "namespace" in options
|
|
503
|
+
and options["namespace"] is not None
|
|
504
|
+
):
|
|
505
|
+
namespace = options.pop("namespace")
|
|
473
506
|
|
|
474
|
-
|
|
507
|
+
if options is not None and "additional_metadata" in options:
|
|
508
|
+
options["additional_metadata"] = inject_carrier_into_metadata(
|
|
509
|
+
options["additional_metadata"], carrier
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
span.set_attributes(
|
|
513
|
+
flatten(
|
|
514
|
+
options["additional_metadata"], parent_key="", separator="."
|
|
515
|
+
)
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
if namespace != "" and not workflow_name.startswith(self.namespace):
|
|
519
|
+
workflow_name = f"{namespace}{workflow_name}"
|
|
520
|
+
|
|
521
|
+
request = self._prepare_workflow_request(workflow_name, input, options)
|
|
522
|
+
|
|
523
|
+
span.add_event(
|
|
524
|
+
"Triggering workflow", attributes={"workflow_name": workflow_name}
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
resp: TriggerWorkflowResponse = self.client.TriggerWorkflow(
|
|
528
|
+
request,
|
|
529
|
+
metadata=get_metadata(self.token),
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
span.add_event(
|
|
533
|
+
"Received workflow response",
|
|
534
|
+
attributes={"workflow_name": workflow_name},
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
return WorkflowRunRef(
|
|
538
|
+
workflow_run_id=resp.workflow_run_id,
|
|
539
|
+
workflow_listener=self.pooled_workflow_listener,
|
|
540
|
+
workflow_run_event_listener=self.listener_client,
|
|
541
|
+
)
|
|
542
|
+
except grpc.RpcError as e:
|
|
543
|
+
if e.code() == grpc.StatusCode.ALREADY_EXISTS:
|
|
544
|
+
raise DedupeViolationErr(e.details())
|
|
545
|
+
|
|
546
|
+
raise ValueError(f"gRPC error: {e}")
|
|
475
547
|
|
|
476
548
|
@tenacity_retry
|
|
477
549
|
def run_workflows(
|
|
478
550
|
self, workflows: List[WorkflowRunDict], options: TriggerWorkflowOptions = None
|
|
479
551
|
) -> list[WorkflowRunRef]:
|
|
480
|
-
|
|
481
552
|
workflow_run_requests: TriggerWorkflowRequest = []
|
|
482
553
|
try:
|
|
483
554
|
if not self.pooled_workflow_listener:
|
|
484
555
|
self.pooled_workflow_listener = PooledWorkflowRunListener(self.config)
|
|
485
556
|
|
|
486
557
|
for workflow in workflows:
|
|
487
|
-
|
|
488
558
|
workflow_name = workflow["workflow_name"]
|
|
489
559
|
input_data = workflow["input"]
|
|
490
560
|
options = workflow["options"]
|
|
@@ -2,7 +2,7 @@ import asyncio
|
|
|
2
2
|
import json
|
|
3
3
|
import time
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from typing import AsyncGenerator, List, Optional
|
|
5
|
+
from typing import Any, AsyncGenerator, List, Optional
|
|
6
6
|
|
|
7
7
|
import grpc
|
|
8
8
|
from grpc._cython import cygrpc
|
|
@@ -23,6 +23,7 @@ from hatchet_sdk.contracts.dispatcher_pb2 import (
|
|
|
23
23
|
from hatchet_sdk.contracts.dispatcher_pb2_grpc import DispatcherStub
|
|
24
24
|
from hatchet_sdk.logger import logger
|
|
25
25
|
from hatchet_sdk.utils.backoff import exp_backoff_sleep
|
|
26
|
+
from hatchet_sdk.utils.serialization import flatten
|
|
26
27
|
|
|
27
28
|
from ...loader import ClientConfig
|
|
28
29
|
from ...metadata import get_metadata
|
|
@@ -88,6 +89,29 @@ class Action:
|
|
|
88
89
|
if not isinstance(self.additional_metadata, dict):
|
|
89
90
|
self.additional_metadata = {}
|
|
90
91
|
|
|
92
|
+
@property
|
|
93
|
+
def otel_attributes(self) -> dict[str, Any]:
|
|
94
|
+
return flatten(
|
|
95
|
+
xs={
|
|
96
|
+
"worker_id": self.worker_id,
|
|
97
|
+
"tenant_id": self.tenant_id,
|
|
98
|
+
"workflow_run_id": self.workflow_run_id,
|
|
99
|
+
"get_group_key_run_id": self.get_group_key_run_id,
|
|
100
|
+
"job_id": self.job_id,
|
|
101
|
+
"job_name": self.job_name,
|
|
102
|
+
"job_run_id": self.job_run_id,
|
|
103
|
+
"step_id": self.step_id,
|
|
104
|
+
"step_run_id": self.step_run_id,
|
|
105
|
+
"retry_count": self.retry_count,
|
|
106
|
+
"child_workflow_index": self.child_workflow_index,
|
|
107
|
+
"child_workflow_key": self.child_workflow_key,
|
|
108
|
+
"parent_workflow_run_id": self.parent_workflow_run_id,
|
|
109
|
+
"action_payload": self.action_payload,
|
|
110
|
+
},
|
|
111
|
+
parent_key="",
|
|
112
|
+
separator=".",
|
|
113
|
+
)
|
|
114
|
+
|
|
91
115
|
|
|
92
116
|
START_STEP_RUN = 0
|
|
93
117
|
CANCEL_STEP_RUN = 1
|
|
@@ -202,7 +226,6 @@ class ActionListener:
|
|
|
202
226
|
listener = None
|
|
203
227
|
|
|
204
228
|
while not self.stop_signal:
|
|
205
|
-
|
|
206
229
|
if listener is not None:
|
|
207
230
|
listener.cancel()
|
|
208
231
|
|
hatchet_sdk/clients/events.py
CHANGED
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import datetime
|
|
3
3
|
import json
|
|
4
4
|
from typing import Any, Dict, List, Optional, TypedDict
|
|
5
|
+
from uuid import uuid4
|
|
5
6
|
|
|
6
7
|
import grpc
|
|
7
8
|
from google.protobuf import timestamp_pb2
|
|
@@ -15,6 +16,13 @@ from hatchet_sdk.contracts.events_pb2 import (
|
|
|
15
16
|
PutStreamEventRequest,
|
|
16
17
|
)
|
|
17
18
|
from hatchet_sdk.contracts.events_pb2_grpc import EventsServiceStub
|
|
19
|
+
from hatchet_sdk.utils.serialization import flatten
|
|
20
|
+
from hatchet_sdk.utils.tracing import (
|
|
21
|
+
create_carrier,
|
|
22
|
+
create_tracer,
|
|
23
|
+
inject_carrier_into_metadata,
|
|
24
|
+
parse_carrier_from_metadata,
|
|
25
|
+
)
|
|
18
26
|
|
|
19
27
|
from ..loader import ClientConfig
|
|
20
28
|
from ..metadata import get_metadata
|
|
@@ -55,6 +63,7 @@ class EventClient:
|
|
|
55
63
|
self.client = client
|
|
56
64
|
self.token = config.token
|
|
57
65
|
self.namespace = config.namespace
|
|
66
|
+
self.otel_tracer = create_tracer(config=config)
|
|
58
67
|
|
|
59
68
|
async def async_push(
|
|
60
69
|
self, event_key, payload, options: Optional[PushEventOptions] = None
|
|
@@ -72,40 +81,54 @@ class EventClient:
|
|
|
72
81
|
|
|
73
82
|
@tenacity_retry
|
|
74
83
|
def push(self, event_key, payload, options: PushEventOptions = None) -> Event:
|
|
75
|
-
|
|
84
|
+
ctx = parse_carrier_from_metadata(
|
|
85
|
+
(options or {}).get("additional_metadata", {})
|
|
86
|
+
)
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
namespace = options["namespace"]
|
|
83
|
-
del options["namespace"]
|
|
88
|
+
with self.otel_tracer.start_as_current_span(
|
|
89
|
+
"hatchet.push", context=ctx
|
|
90
|
+
) as span:
|
|
91
|
+
carrier = create_carrier()
|
|
92
|
+
namespace = self.namespace
|
|
84
93
|
|
|
85
|
-
|
|
94
|
+
if (
|
|
95
|
+
options is not None
|
|
96
|
+
and "namespace" in options
|
|
97
|
+
and options["namespace"] is not None
|
|
98
|
+
):
|
|
99
|
+
namespace = options.pop("namespace")
|
|
86
100
|
|
|
87
|
-
|
|
88
|
-
meta = None if options is None else options["additional_metadata"]
|
|
89
|
-
meta_bytes = None if meta is None else json.dumps(meta).encode("utf-8")
|
|
90
|
-
except Exception as e:
|
|
91
|
-
raise ValueError(f"Error encoding meta: {e}")
|
|
101
|
+
namespaced_event_key = namespace + event_key
|
|
92
102
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
eventTimestamp=proto_timestamp_now(),
|
|
102
|
-
additionalMetadata=meta_bytes,
|
|
103
|
-
)
|
|
103
|
+
try:
|
|
104
|
+
meta = inject_carrier_into_metadata(
|
|
105
|
+
dict() if options is None else options["additional_metadata"],
|
|
106
|
+
carrier,
|
|
107
|
+
)
|
|
108
|
+
meta_bytes = None if meta is None else json.dumps(meta).encode("utf-8")
|
|
109
|
+
except Exception as e:
|
|
110
|
+
raise ValueError(f"Error encoding meta: {e}")
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
span.set_attributes(flatten(meta, parent_key="", separator="."))
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
payload_bytes = json.dumps(payload).encode("utf-8")
|
|
116
|
+
except json.UnicodeEncodeError as e:
|
|
117
|
+
raise ValueError(f"Error encoding payload: {e}")
|
|
118
|
+
|
|
119
|
+
request = PushEventRequest(
|
|
120
|
+
key=namespaced_event_key,
|
|
121
|
+
payload=payload_bytes,
|
|
122
|
+
eventTimestamp=proto_timestamp_now(),
|
|
123
|
+
additionalMetadata=meta_bytes,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
span.add_event("Pushing event", attributes={"key": namespaced_event_key})
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
return self.client.Push(request, metadata=get_metadata(self.token))
|
|
130
|
+
except grpc.RpcError as e:
|
|
131
|
+
raise ValueError(f"gRPC error: {e}")
|
|
109
132
|
|
|
110
133
|
@tenacity_retry
|
|
111
134
|
def bulk_push(
|
|
@@ -114,41 +137,57 @@ class EventClient:
|
|
|
114
137
|
options: BulkPushEventOptions = None,
|
|
115
138
|
) -> List[Event]:
|
|
116
139
|
namespace = self.namespace
|
|
140
|
+
bulk_push_correlation_id = uuid4()
|
|
141
|
+
ctx = parse_carrier_from_metadata(
|
|
142
|
+
(options or {}).get("additional_metadata", {})
|
|
143
|
+
)
|
|
117
144
|
|
|
118
145
|
if (
|
|
119
146
|
options is not None
|
|
120
147
|
and "namespace" in options
|
|
121
148
|
and options["namespace"] is not None
|
|
122
149
|
):
|
|
123
|
-
namespace = options
|
|
124
|
-
del options["namespace"]
|
|
150
|
+
namespace = options.pop("namespace")
|
|
125
151
|
|
|
126
152
|
bulk_events = []
|
|
127
153
|
for event in events:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
with self.otel_tracer.start_as_current_span(
|
|
155
|
+
"hatchet.bulk_push", context=ctx
|
|
156
|
+
) as span:
|
|
157
|
+
carrier = create_carrier()
|
|
158
|
+
span.set_attribute(
|
|
159
|
+
"bulk_push_correlation_id", str(bulk_push_correlation_id)
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
event_key = namespace + event["key"]
|
|
163
|
+
payload = event["payload"]
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
meta = inject_carrier_into_metadata(
|
|
167
|
+
event.get("additional_metadata", {}), carrier
|
|
168
|
+
)
|
|
169
|
+
meta_bytes = json.dumps(meta).encode("utf-8") if meta else None
|
|
170
|
+
except Exception as e:
|
|
171
|
+
raise ValueError(f"Error encoding meta: {e}")
|
|
172
|
+
|
|
173
|
+
span.set_attributes(flatten(meta, parent_key="", separator="."))
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
payload_bytes = json.dumps(payload).encode("utf-8")
|
|
177
|
+
except json.UnicodeEncodeError as e:
|
|
178
|
+
raise ValueError(f"Error encoding payload: {e}")
|
|
179
|
+
|
|
180
|
+
request = PushEventRequest(
|
|
181
|
+
key=event_key,
|
|
182
|
+
payload=payload_bytes,
|
|
183
|
+
eventTimestamp=proto_timestamp_now(),
|
|
184
|
+
additionalMetadata=meta_bytes,
|
|
185
|
+
)
|
|
186
|
+
bulk_events.append(request)
|
|
149
187
|
|
|
150
188
|
bulk_request = BulkPushEventRequest(events=bulk_events)
|
|
151
189
|
|
|
190
|
+
span.add_event("Pushing bulk events")
|
|
152
191
|
try:
|
|
153
192
|
response = self.client.BulkPush(
|
|
154
193
|
bulk_request, metadata=get_metadata(self.token)
|
|
@@ -70,6 +70,9 @@ from hatchet_sdk.clients.rest.models.create_api_token_request import (
|
|
|
70
70
|
from hatchet_sdk.clients.rest.models.create_api_token_response import (
|
|
71
71
|
CreateAPITokenResponse,
|
|
72
72
|
)
|
|
73
|
+
from hatchet_sdk.clients.rest.models.create_cron_workflow_trigger_request import (
|
|
74
|
+
CreateCronWorkflowTriggerRequest,
|
|
75
|
+
)
|
|
73
76
|
from hatchet_sdk.clients.rest.models.create_event_request import CreateEventRequest
|
|
74
77
|
from hatchet_sdk.clients.rest.models.create_pull_request_from_step_run import (
|
|
75
78
|
CreatePullRequestFromStepRun,
|
|
@@ -84,6 +87,11 @@ from hatchet_sdk.clients.rest.models.create_tenant_invite_request import (
|
|
|
84
87
|
CreateTenantInviteRequest,
|
|
85
88
|
)
|
|
86
89
|
from hatchet_sdk.clients.rest.models.create_tenant_request import CreateTenantRequest
|
|
90
|
+
from hatchet_sdk.clients.rest.models.cron_workflows import CronWorkflows
|
|
91
|
+
from hatchet_sdk.clients.rest.models.cron_workflows_list import CronWorkflowsList
|
|
92
|
+
from hatchet_sdk.clients.rest.models.cron_workflows_order_by_field import (
|
|
93
|
+
CronWorkflowsOrderByField,
|
|
94
|
+
)
|
|
87
95
|
from hatchet_sdk.clients.rest.models.event import Event
|
|
88
96
|
from hatchet_sdk.clients.rest.models.event_data import EventData
|
|
89
97
|
from hatchet_sdk.clients.rest.models.event_key_list import EventKeyList
|
|
@@ -141,6 +149,17 @@ from hatchet_sdk.clients.rest.models.replay_workflow_runs_response import (
|
|
|
141
149
|
ReplayWorkflowRunsResponse,
|
|
142
150
|
)
|
|
143
151
|
from hatchet_sdk.clients.rest.models.rerun_step_run_request import RerunStepRunRequest
|
|
152
|
+
from hatchet_sdk.clients.rest.models.schedule_workflow_run_request import (
|
|
153
|
+
ScheduleWorkflowRunRequest,
|
|
154
|
+
)
|
|
155
|
+
from hatchet_sdk.clients.rest.models.scheduled_run_status import ScheduledRunStatus
|
|
156
|
+
from hatchet_sdk.clients.rest.models.scheduled_workflows import ScheduledWorkflows
|
|
157
|
+
from hatchet_sdk.clients.rest.models.scheduled_workflows_list import (
|
|
158
|
+
ScheduledWorkflowsList,
|
|
159
|
+
)
|
|
160
|
+
from hatchet_sdk.clients.rest.models.scheduled_workflows_order_by_field import (
|
|
161
|
+
ScheduledWorkflowsOrderByField,
|
|
162
|
+
)
|
|
144
163
|
from hatchet_sdk.clients.rest.models.semaphore_slots import SemaphoreSlots
|
|
145
164
|
from hatchet_sdk.clients.rest.models.slack_webhook import SlackWebhook
|
|
146
165
|
from hatchet_sdk.clients.rest.models.sns_integration import SNSIntegration
|
|
@@ -219,6 +238,8 @@ from hatchet_sdk.clients.rest.models.webhook_worker_request_method import (
|
|
|
219
238
|
from hatchet_sdk.clients.rest.models.worker import Worker
|
|
220
239
|
from hatchet_sdk.clients.rest.models.worker_label import WorkerLabel
|
|
221
240
|
from hatchet_sdk.clients.rest.models.worker_list import WorkerList
|
|
241
|
+
from hatchet_sdk.clients.rest.models.worker_runtime_info import WorkerRuntimeInfo
|
|
242
|
+
from hatchet_sdk.clients.rest.models.worker_runtime_sdks import WorkerRuntimeSDKs
|
|
222
243
|
from hatchet_sdk.clients.rest.models.workflow import Workflow
|
|
223
244
|
from hatchet_sdk.clients.rest.models.workflow_concurrency import WorkflowConcurrency
|
|
224
245
|
from hatchet_sdk.clients.rest.models.workflow_kind import WorkflowKind
|
|
@@ -298,9 +298,10 @@ class APITokenApi:
|
|
|
298
298
|
_body_params = create_api_token_request
|
|
299
299
|
|
|
300
300
|
# set the HTTP header `Accept`
|
|
301
|
-
|
|
302
|
-
["
|
|
303
|
-
|
|
301
|
+
if "Accept" not in _header_params:
|
|
302
|
+
_header_params["Accept"] = self.api_client.select_header_accept(
|
|
303
|
+
["application/json"]
|
|
304
|
+
)
|
|
304
305
|
|
|
305
306
|
# set the HTTP header `Content-Type`
|
|
306
307
|
if _content_type:
|
|
@@ -570,9 +571,10 @@ class APITokenApi:
|
|
|
570
571
|
# process the body parameter
|
|
571
572
|
|
|
572
573
|
# set the HTTP header `Accept`
|
|
573
|
-
|
|
574
|
-
["
|
|
575
|
-
|
|
574
|
+
if "Accept" not in _header_params:
|
|
575
|
+
_header_params["Accept"] = self.api_client.select_header_accept(
|
|
576
|
+
["application/json"]
|
|
577
|
+
)
|
|
576
578
|
|
|
577
579
|
# authentication setting
|
|
578
580
|
_auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
|
|
@@ -832,9 +834,10 @@ class APITokenApi:
|
|
|
832
834
|
# process the body parameter
|
|
833
835
|
|
|
834
836
|
# set the HTTP header `Accept`
|
|
835
|
-
|
|
836
|
-
["
|
|
837
|
-
|
|
837
|
+
if "Accept" not in _header_params:
|
|
838
|
+
_header_params["Accept"] = self.api_client.select_header_accept(
|
|
839
|
+
["application/json"]
|
|
840
|
+
)
|
|
838
841
|
|
|
839
842
|
# authentication setting
|
|
840
843
|
_auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
|