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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from functools import cache
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from opentelemetry import trace
|
|
6
|
+
from opentelemetry.context import Context
|
|
7
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
8
|
+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
|
|
9
|
+
from opentelemetry.sdk.trace import Tracer, TracerProvider
|
|
10
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
11
|
+
from opentelemetry.trace import NoOpTracerProvider
|
|
12
|
+
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
13
|
+
|
|
14
|
+
from hatchet_sdk.loader import ClientConfig
|
|
15
|
+
|
|
16
|
+
OTEL_CARRIER_KEY = "__otel_carrier"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@cache
|
|
20
|
+
def create_tracer(config: ClientConfig) -> Tracer:
|
|
21
|
+
## TODO: Figure out how to specify protocol here
|
|
22
|
+
resource = Resource(
|
|
23
|
+
attributes={SERVICE_NAME: config.otel_service_name or "hatchet.run"}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if config.otel_exporter_oltp_endpoint and config.otel_exporter_oltp_headers:
|
|
27
|
+
processor = BatchSpanProcessor(
|
|
28
|
+
OTLPSpanExporter(
|
|
29
|
+
endpoint=config.otel_exporter_oltp_endpoint,
|
|
30
|
+
headers=config.otel_exporter_oltp_headers,
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
## If tracer provider is already set, we don't need to override it
|
|
35
|
+
if not isinstance(trace.get_tracer_provider(), TracerProvider):
|
|
36
|
+
trace_provider = TracerProvider(resource=resource)
|
|
37
|
+
trace_provider.add_span_processor(processor)
|
|
38
|
+
trace.set_tracer_provider(trace_provider)
|
|
39
|
+
else:
|
|
40
|
+
if not isinstance(trace.get_tracer_provider(), NoOpTracerProvider):
|
|
41
|
+
trace.set_tracer_provider(NoOpTracerProvider())
|
|
42
|
+
|
|
43
|
+
return trace.get_tracer(__name__)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def create_carrier() -> dict[str, str]:
|
|
47
|
+
carrier = {}
|
|
48
|
+
TraceContextTextMapPropagator().inject(carrier)
|
|
49
|
+
|
|
50
|
+
return carrier
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def inject_carrier_into_metadata(
|
|
54
|
+
metadata: dict[Any, Any], carrier: dict[str, str]
|
|
55
|
+
) -> dict[Any, Any]:
|
|
56
|
+
if carrier:
|
|
57
|
+
metadata[OTEL_CARRIER_KEY] = carrier
|
|
58
|
+
|
|
59
|
+
return metadata
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def parse_carrier_from_metadata(metadata: dict[str, Any]) -> Context:
|
|
63
|
+
return (
|
|
64
|
+
TraceContextTextMapPropagator().extract(_ctx)
|
|
65
|
+
if (_ctx := metadata.get(OTEL_CARRIER_KEY))
|
|
66
|
+
else None
|
|
67
|
+
)
|
|
@@ -3,21 +3,19 @@ import contextvars
|
|
|
3
3
|
import ctypes
|
|
4
4
|
import functools
|
|
5
5
|
import json
|
|
6
|
-
import logging
|
|
7
6
|
import traceback
|
|
8
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
9
8
|
from enum import Enum
|
|
10
|
-
from io import StringIO
|
|
11
|
-
from logging import StreamHandler
|
|
12
9
|
from multiprocessing import Queue
|
|
13
10
|
from threading import Thread, current_thread
|
|
14
|
-
from typing import Any, Callable,
|
|
11
|
+
from typing import Any, Callable, Dict
|
|
12
|
+
|
|
13
|
+
from opentelemetry.trace import StatusCode
|
|
15
14
|
|
|
16
15
|
from hatchet_sdk.client import new_client_raw
|
|
17
16
|
from hatchet_sdk.clients.admin import new_admin
|
|
18
17
|
from hatchet_sdk.clients.dispatcher.action_listener import Action
|
|
19
18
|
from hatchet_sdk.clients.dispatcher.dispatcher import new_dispatcher
|
|
20
|
-
from hatchet_sdk.clients.events import EventClient
|
|
21
19
|
from hatchet_sdk.clients.run_event_listener import new_listener
|
|
22
20
|
from hatchet_sdk.clients.workflow_listener import PooledWorkflowRunListener
|
|
23
21
|
from hatchet_sdk.context import Context
|
|
@@ -33,6 +31,7 @@ from hatchet_sdk.contracts.dispatcher_pb2 import (
|
|
|
33
31
|
)
|
|
34
32
|
from hatchet_sdk.loader import ClientConfig
|
|
35
33
|
from hatchet_sdk.logger import logger
|
|
34
|
+
from hatchet_sdk.utils.tracing import create_tracer, parse_carrier_from_metadata
|
|
36
35
|
from hatchet_sdk.v2.callable import DurableContext
|
|
37
36
|
from hatchet_sdk.worker.action_listener_process import ActionEvent
|
|
38
37
|
from hatchet_sdk.worker.runner.utils.capture_logs import copy_context_vars, sr, wr
|
|
@@ -85,26 +84,43 @@ class Runner:
|
|
|
85
84
|
labels=labels, client=new_client_raw(config).dispatcher
|
|
86
85
|
)
|
|
87
86
|
|
|
87
|
+
self.otel_tracer = create_tracer(config=config)
|
|
88
|
+
|
|
89
|
+
def create_workflow_run_url(self, action: Action) -> str:
|
|
90
|
+
return f"{self.config.server_url}/workflow-runs/{action.workflow_run_id}?tenant={action.tenant_id}"
|
|
91
|
+
|
|
88
92
|
def run(self, action: Action):
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
93
|
+
ctx = parse_carrier_from_metadata(action.additional_metadata)
|
|
94
|
+
|
|
95
|
+
with self.otel_tracer.start_as_current_span(
|
|
96
|
+
f"hatchet.worker.run.{action.step_id}", context=ctx
|
|
97
|
+
) as span:
|
|
98
|
+
if self.worker_context.id() is None:
|
|
99
|
+
self.worker_context._worker_id = action.worker_id
|
|
100
|
+
|
|
101
|
+
span.set_attributes(action.otel_attributes)
|
|
102
|
+
span.set_attribute("workflow_run_url", self.create_workflow_run_url(action))
|
|
103
|
+
|
|
104
|
+
match action.action_type:
|
|
105
|
+
case ActionType.START_STEP_RUN:
|
|
106
|
+
log = f"run: start step: {action.action_id}/{action.step_run_id}"
|
|
107
|
+
span.add_event(log)
|
|
108
|
+
logger.info(log)
|
|
109
|
+
asyncio.create_task(self.handle_start_step_run(action))
|
|
110
|
+
case ActionType.CANCEL_STEP_RUN:
|
|
111
|
+
log = f"cancel: step run: {action.action_id}/{action.step_run_id}"
|
|
112
|
+
span.add_event(log)
|
|
113
|
+
logger.info(log)
|
|
114
|
+
asyncio.create_task(self.handle_cancel_action(action.step_run_id))
|
|
115
|
+
case ActionType.START_GET_GROUP_KEY:
|
|
116
|
+
log = f"run: get group key: {action.action_id}/{action.get_group_key_run_id}"
|
|
117
|
+
span.add_event(log)
|
|
118
|
+
logger.info(log)
|
|
119
|
+
asyncio.create_task(self.handle_start_group_key_run(action))
|
|
120
|
+
case _:
|
|
121
|
+
log = f"unknown action type: {action.action_type}"
|
|
122
|
+
span.add_event(log)
|
|
123
|
+
logger.error(log)
|
|
108
124
|
|
|
109
125
|
def step_run_callback(self, action: Action):
|
|
110
126
|
def inner_callback(task: asyncio.Task):
|
|
@@ -248,16 +264,11 @@ class Runner:
|
|
|
248
264
|
if run_id in self.contexts:
|
|
249
265
|
del self.contexts[run_id]
|
|
250
266
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
# Find the corresponding action function from the registry
|
|
255
|
-
action_func = self.action_registry.get(action_name)
|
|
256
|
-
|
|
257
|
-
context: Context | DurableContext
|
|
258
|
-
|
|
267
|
+
def create_context(
|
|
268
|
+
self, action: Action, action_func: Callable[..., Any] | None
|
|
269
|
+
) -> Context | DurableContext:
|
|
259
270
|
if hasattr(action_func, "durable") and action_func.durable:
|
|
260
|
-
|
|
271
|
+
return DurableContext(
|
|
261
272
|
action,
|
|
262
273
|
self.dispatcher_client,
|
|
263
274
|
self.admin_client,
|
|
@@ -268,48 +279,8 @@ class Runner:
|
|
|
268
279
|
self.worker_context,
|
|
269
280
|
self.client.config.namespace,
|
|
270
281
|
)
|
|
271
|
-
else:
|
|
272
|
-
context = Context(
|
|
273
|
-
action,
|
|
274
|
-
self.dispatcher_client,
|
|
275
|
-
self.admin_client,
|
|
276
|
-
self.client.event,
|
|
277
|
-
self.client.rest,
|
|
278
|
-
self.client.workflow_listener,
|
|
279
|
-
self.workflow_run_event_listener,
|
|
280
|
-
self.worker_context,
|
|
281
|
-
self.client.config.namespace,
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
self.contexts[action.step_run_id] = context
|
|
285
|
-
|
|
286
|
-
if action_func:
|
|
287
|
-
self.event_queue.put(
|
|
288
|
-
ActionEvent(
|
|
289
|
-
action=action,
|
|
290
|
-
type=STEP_EVENT_TYPE_STARTED,
|
|
291
|
-
)
|
|
292
|
-
)
|
|
293
|
-
|
|
294
|
-
loop = asyncio.get_event_loop()
|
|
295
|
-
task = loop.create_task(
|
|
296
|
-
self.async_wrapped_action_func(
|
|
297
|
-
context, action_func, action, action.step_run_id
|
|
298
|
-
)
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
task.add_done_callback(self.step_run_callback(action))
|
|
302
|
-
self.tasks[action.step_run_id] = task
|
|
303
|
-
|
|
304
|
-
try:
|
|
305
|
-
await task
|
|
306
|
-
except Exception:
|
|
307
|
-
# do nothing, this should be caught in the callback
|
|
308
|
-
pass
|
|
309
282
|
|
|
310
|
-
|
|
311
|
-
action_name = action.action_id
|
|
312
|
-
context = Context(
|
|
283
|
+
return Context(
|
|
313
284
|
action,
|
|
314
285
|
self.dispatcher_client,
|
|
315
286
|
self.admin_client,
|
|
@@ -320,35 +291,101 @@ class Runner:
|
|
|
320
291
|
self.worker_context,
|
|
321
292
|
self.client.config.namespace,
|
|
322
293
|
)
|
|
323
|
-
self.contexts[action.get_group_key_run_id] = context
|
|
324
294
|
|
|
325
|
-
|
|
326
|
-
|
|
295
|
+
async def handle_start_step_run(self, action: Action):
|
|
296
|
+
with self.otel_tracer.start_as_current_span(
|
|
297
|
+
f"hatchet.worker.handle_start_step_run.{action.step_id}",
|
|
298
|
+
) as span:
|
|
299
|
+
span.add_event("Starting step run")
|
|
300
|
+
span.set_attributes(action.otel_attributes)
|
|
301
|
+
|
|
302
|
+
action_name = action.action_id
|
|
303
|
+
|
|
304
|
+
# Find the corresponding action function from the registry
|
|
305
|
+
action_func = self.action_registry.get(action_name)
|
|
306
|
+
|
|
307
|
+
context = self.create_context(action, action_func)
|
|
308
|
+
|
|
309
|
+
self.contexts[action.step_run_id] = context
|
|
310
|
+
|
|
311
|
+
if action_func:
|
|
312
|
+
self.event_queue.put(
|
|
313
|
+
ActionEvent(
|
|
314
|
+
action=action,
|
|
315
|
+
type=STEP_EVENT_TYPE_STARTED,
|
|
316
|
+
)
|
|
317
|
+
)
|
|
327
318
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
type=GROUP_KEY_EVENT_TYPE_STARTED,
|
|
319
|
+
loop = asyncio.get_event_loop()
|
|
320
|
+
task = loop.create_task(
|
|
321
|
+
self.async_wrapped_action_func(
|
|
322
|
+
context, action_func, action, action.step_run_id
|
|
323
|
+
)
|
|
334
324
|
)
|
|
325
|
+
|
|
326
|
+
task.add_done_callback(self.step_run_callback(action))
|
|
327
|
+
self.tasks[action.step_run_id] = task
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
await task
|
|
331
|
+
span.set_status(StatusCode.OK)
|
|
332
|
+
except Exception as e:
|
|
333
|
+
# do nothing, this should be caught in the callback
|
|
334
|
+
span.set_status(StatusCode.ERROR)
|
|
335
|
+
span.record_exception(e)
|
|
336
|
+
|
|
337
|
+
span.add_event("Finished step run")
|
|
338
|
+
|
|
339
|
+
async def handle_start_group_key_run(self, action: Action):
|
|
340
|
+
with self.otel_tracer.start_as_current_span(
|
|
341
|
+
f"hatchet.worker.handle_start_step_run.{action.step_id}"
|
|
342
|
+
) as span:
|
|
343
|
+
span.add_event("Starting group key run")
|
|
344
|
+
action_name = action.action_id
|
|
345
|
+
context = Context(
|
|
346
|
+
action,
|
|
347
|
+
self.dispatcher_client,
|
|
348
|
+
self.admin_client,
|
|
349
|
+
self.client.event,
|
|
350
|
+
self.client.rest,
|
|
351
|
+
self.client.workflow_listener,
|
|
352
|
+
self.workflow_run_event_listener,
|
|
353
|
+
self.worker_context,
|
|
354
|
+
self.client.config.namespace,
|
|
335
355
|
)
|
|
356
|
+
self.contexts[action.get_group_key_run_id] = context
|
|
357
|
+
|
|
358
|
+
# Find the corresponding action function from the registry
|
|
359
|
+
action_func = self.action_registry.get(action_name)
|
|
336
360
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
self.
|
|
340
|
-
|
|
361
|
+
if action_func:
|
|
362
|
+
# send an event that the group key run has started
|
|
363
|
+
self.event_queue.put(
|
|
364
|
+
ActionEvent(
|
|
365
|
+
action=action,
|
|
366
|
+
type=GROUP_KEY_EVENT_TYPE_STARTED,
|
|
367
|
+
)
|
|
341
368
|
)
|
|
342
|
-
)
|
|
343
369
|
|
|
344
|
-
|
|
345
|
-
|
|
370
|
+
loop = asyncio.get_event_loop()
|
|
371
|
+
task = loop.create_task(
|
|
372
|
+
self.async_wrapped_action_func(
|
|
373
|
+
context, action_func, action, action.get_group_key_run_id
|
|
374
|
+
)
|
|
375
|
+
)
|
|
346
376
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
377
|
+
task.add_done_callback(self.group_key_run_callback(action))
|
|
378
|
+
self.tasks[action.get_group_key_run_id] = task
|
|
379
|
+
|
|
380
|
+
try:
|
|
381
|
+
await task
|
|
382
|
+
span.set_status(StatusCode.OK)
|
|
383
|
+
except Exception as e:
|
|
384
|
+
# do nothing, this should be caught in the callback
|
|
385
|
+
span.set_status(StatusCode.ERROR)
|
|
386
|
+
span.record_exception(e)
|
|
387
|
+
|
|
388
|
+
span.add_event("Finished group key run")
|
|
352
389
|
|
|
353
390
|
def force_kill_thread(self, thread):
|
|
354
391
|
"""Terminate a python threading.Thread."""
|
|
@@ -380,27 +417,36 @@ class Runner:
|
|
|
380
417
|
logger.exception(f"Failed to terminate thread: {e}")
|
|
381
418
|
|
|
382
419
|
async def handle_cancel_action(self, run_id: str):
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
420
|
+
with self.otel_tracer.start_as_current_span(
|
|
421
|
+
"hatchet.worker.handle_cancel_action"
|
|
422
|
+
) as span:
|
|
423
|
+
span.add_event(f"Cancelling run id: {run_id}")
|
|
424
|
+
span.set_attribute("run_id", run_id)
|
|
388
425
|
|
|
389
|
-
|
|
426
|
+
try:
|
|
427
|
+
# call cancel to signal the context to stop
|
|
428
|
+
if run_id in self.contexts:
|
|
429
|
+
context = self.contexts.get(run_id)
|
|
430
|
+
context.cancel()
|
|
390
431
|
|
|
391
|
-
|
|
392
|
-
future = self.tasks.get(run_id)
|
|
432
|
+
await asyncio.sleep(1)
|
|
393
433
|
|
|
394
|
-
if
|
|
395
|
-
future.
|
|
434
|
+
if run_id in self.tasks:
|
|
435
|
+
future = self.tasks.get(run_id)
|
|
396
436
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
437
|
+
if future:
|
|
438
|
+
future.cancel()
|
|
439
|
+
|
|
440
|
+
# check if thread is still running, if so, print a warning
|
|
441
|
+
if run_id in self.threads:
|
|
442
|
+
logger.warning(
|
|
443
|
+
f"Thread {self.threads[run_id].ident} with run id {run_id} is still running after cancellation. This could cause the thread pool to get blocked and prevent new tasks from running."
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
span.set_status(StatusCode.OK)
|
|
447
|
+
finally:
|
|
448
|
+
self.cleanup_run_id(run_id)
|
|
449
|
+
span.add_event(f"Finished cancelling run id: {run_id}")
|
|
404
450
|
|
|
405
451
|
def serialize_output(self, output: Any) -> str:
|
|
406
452
|
output_bytes = ""
|
hatchet_sdk/worker/worker.py
CHANGED
|
@@ -9,7 +9,6 @@ from multiprocessing import Process, Queue
|
|
|
9
9
|
from typing import Any, Callable, Dict, Optional
|
|
10
10
|
|
|
11
11
|
from hatchet_sdk.client import Client, new_client_raw
|
|
12
|
-
from hatchet_sdk.compute.managed_compute import ManagedCompute
|
|
13
12
|
from hatchet_sdk.context import Context
|
|
14
13
|
from hatchet_sdk.contracts.workflows_pb2 import CreateWorkflowVersionOpts
|
|
15
14
|
from hatchet_sdk.loader import ClientConfig
|
|
@@ -100,17 +99,7 @@ class Worker:
|
|
|
100
99
|
return action_function
|
|
101
100
|
|
|
102
101
|
for action_name, action_func in workflow.get_actions(namespace):
|
|
103
|
-
|
|
104
|
-
self.client.config.runnable_actions
|
|
105
|
-
and action_name not in self.client.config.runnable_actions
|
|
106
|
-
):
|
|
107
|
-
logger.debug(f"skipping action: {action_name} not in runnable actions")
|
|
108
|
-
continue
|
|
109
|
-
|
|
110
|
-
fn = create_action_function(action_func)
|
|
111
|
-
# copy the compute from the action func to the action function
|
|
112
|
-
fn._step_compute = action_func._step_compute
|
|
113
|
-
self.action_registry[action_name] = fn
|
|
102
|
+
self.action_registry[action_name] = create_action_function(action_func)
|
|
114
103
|
|
|
115
104
|
def status(self) -> WorkerStatus:
|
|
116
105
|
return self._status
|
|
@@ -165,11 +154,6 @@ class Worker:
|
|
|
165
154
|
if not _from_start:
|
|
166
155
|
self.setup_loop(options.loop)
|
|
167
156
|
|
|
168
|
-
managed_compute = ManagedCompute(
|
|
169
|
-
self.action_registry, self.client, self.max_runs
|
|
170
|
-
)
|
|
171
|
-
await managed_compute.cloud_register()
|
|
172
|
-
|
|
173
157
|
self.action_listener_process = self._start_listener()
|
|
174
158
|
self.action_runner = self._run_action_runner()
|
|
175
159
|
self.action_listener_health_check = self.loop.create_task(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hatchet-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.41.0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Alexander Belanger
|
|
6
6
|
Author-email: alexander@hatchet.run
|
|
@@ -16,6 +16,12 @@ Requires-Dist: grpcio (>=1.64.1,<2.0.0)
|
|
|
16
16
|
Requires-Dist: grpcio-tools (>=1.60.0,<2.0.0)
|
|
17
17
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
18
18
|
Requires-Dist: nest-asyncio (>=1.6.0,<2.0.0)
|
|
19
|
+
Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0)
|
|
20
|
+
Requires-Dist: opentelemetry-distro (>=0.48b0,<0.49)
|
|
21
|
+
Requires-Dist: opentelemetry-exporter-otlp (>=1.27.0,<2.0.0)
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0)
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation (>=0.48b0,<0.49)
|
|
24
|
+
Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0)
|
|
19
25
|
Requires-Dist: protobuf (>=4.25.2,<5.0.0)
|
|
20
26
|
Requires-Dist: pydantic (>=2.6.3,<3.0.0)
|
|
21
27
|
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
@@ -27,5 +33,5 @@ Description-Content-Type: text/markdown
|
|
|
27
33
|
|
|
28
34
|
# Hatchet Python SDK
|
|
29
35
|
|
|
30
|
-
This is the [Hatchet](https://hatchet.run) Python SDK. For usage, see the [docs](https://docs.hatchet.run
|
|
36
|
+
This is the [Hatchet](https://hatchet.run) Python SDK. For usage, see the [docs](https://docs.hatchet.run).
|
|
31
37
|
|