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,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, Coroutine, Dict
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
- if self.worker_context.id() is None:
90
- self.worker_context._worker_id = action.worker_id
91
-
92
- match action.action_type:
93
- case ActionType.START_STEP_RUN:
94
- logger.info(f"run: start step: {action.action_id}/{action.step_run_id}")
95
- asyncio.create_task(self.handle_start_step_run(action))
96
- case ActionType.CANCEL_STEP_RUN:
97
- logger.info(
98
- f"cancel: step run: {action.action_id}/{action.step_run_id}"
99
- )
100
- asyncio.create_task(self.handle_cancel_action(action.step_run_id))
101
- case ActionType.START_GET_GROUP_KEY:
102
- logger.info(
103
- f"run: get group key: {action.action_id}/{action.get_group_key_run_id}"
104
- )
105
- asyncio.create_task(self.handle_start_group_key_run(action))
106
- case _:
107
- logger.error(f"unknown action type: {action.action_type}")
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
- async def handle_start_step_run(self, action: Action):
252
- action_name = action.action_id
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
- context = DurableContext(
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
- async def handle_start_group_key_run(self, action: Action):
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
- # Find the corresponding action function from the registry
326
- action_func = self.action_registry.get(action_name)
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
- if action_func:
329
- # send an event that the group key run has started
330
- self.event_queue.put(
331
- ActionEvent(
332
- action=action,
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
- loop = asyncio.get_event_loop()
338
- task = loop.create_task(
339
- self.async_wrapped_action_func(
340
- context, action_func, action, action.get_group_key_run_id
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
- task.add_done_callback(self.group_key_run_callback(action))
345
- self.tasks[action.get_group_key_run_id] = task
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
- try:
348
- await task
349
- except Exception:
350
- # do nothing, this should be caught in the callback
351
- pass
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
- try:
384
- # call cancel to signal the context to stop
385
- if run_id in self.contexts:
386
- context = self.contexts.get(run_id)
387
- context.cancel()
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
- await asyncio.sleep(1)
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
- if run_id in self.tasks:
392
- future = self.tasks.get(run_id)
432
+ await asyncio.sleep(1)
393
433
 
394
- if future:
395
- future.cancel()
434
+ if run_id in self.tasks:
435
+ future = self.tasks.get(run_id)
396
436
 
397
- # check if thread is still running, if so, print a warning
398
- if run_id in self.threads:
399
- logger.warning(
400
- 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."
401
- )
402
- finally:
403
- self.cleanup_run_id(run_id)
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 = ""
@@ -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
- if (
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.40.0a8
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/sdks/python-sdk/).
36
+ This is the [Hatchet](https://hatchet.run) Python SDK. For usage, see the [docs](https://docs.hatchet.run).
31
37