durabletask 1.3.0.dev22__tar.gz → 1.3.0.dev23__tar.gz

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.
Files changed (38) hide show
  1. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/PKG-INFO +4 -1
  2. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/client.py +50 -23
  3. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/helpers.py +12 -6
  4. durabletask-1.3.0.dev23/durabletask/internal/tracing.py +863 -0
  5. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/task.py +2 -2
  6. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/worker.py +301 -46
  7. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask.egg-info/PKG-INFO +4 -1
  8. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask.egg-info/SOURCES.txt +1 -0
  9. durabletask-1.3.0.dev23/durabletask.egg-info/requires.txt +8 -0
  10. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/pyproject.toml +7 -1
  11. durabletask-1.3.0.dev22/durabletask.egg-info/requires.txt +0 -4
  12. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/LICENSE +0 -0
  13. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/README.md +0 -0
  14. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/__init__.py +0 -0
  15. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/__init__.py +0 -0
  16. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/durable_entity.py +0 -0
  17. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/entity_context.py +0 -0
  18. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/entity_instance_id.py +0 -0
  19. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/entity_lock.py +0 -0
  20. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/entity_metadata.py +0 -0
  21. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/entities/entity_operation_failed_exception.py +0 -0
  22. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/client_helpers.py +0 -0
  23. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/entity_state_shim.py +0 -0
  24. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/exceptions.py +0 -0
  25. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/grpc_interceptor.py +0 -0
  26. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/json_encode_output_exception.py +0 -0
  27. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/orchestration_entity_context.py +0 -0
  28. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/orchestrator_service_pb2.py +0 -0
  29. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/orchestrator_service_pb2.pyi +0 -0
  30. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/orchestrator_service_pb2_grpc.py +0 -0
  31. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/proto_task_hub_sidecar_service_stub.py +0 -0
  32. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/internal/shared.py +0 -0
  33. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/py.typed +0 -0
  34. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/testing/__init__.py +0 -0
  35. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask/testing/in_memory_backend.py +0 -0
  36. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask.egg-info/dependency_links.txt +0 -0
  37. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/durabletask.egg-info/top_level.txt +0 -0
  38. {durabletask-1.3.0.dev22 → durabletask-1.3.0.dev23}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: durabletask
3
- Version: 1.3.0.dev22
3
+ Version: 1.3.0.dev23
4
4
  Summary: A Durable Task Client SDK for Python
5
5
  License: MIT License
6
6
 
@@ -37,6 +37,9 @@ Requires-Dist: grpcio
37
37
  Requires-Dist: protobuf
38
38
  Requires-Dist: asyncio
39
39
  Requires-Dist: packaging
40
+ Provides-Extra: opentelemetry
41
+ Requires-Dist: opentelemetry-api>=1.0.0; extra == "opentelemetry"
42
+ Requires-Dist: opentelemetry-sdk>=1.0.0; extra == "opentelemetry"
40
43
  Dynamic: license-file
41
44
 
42
45
  # Durable Task SDK for Python
@@ -2,6 +2,7 @@
2
2
  # Licensed under the MIT License.
3
3
 
4
4
  import logging
5
+ import uuid
5
6
  from dataclasses import dataclass
6
7
  from datetime import datetime
7
8
  from enum import Enum
@@ -16,6 +17,7 @@ import durabletask.internal.helpers as helpers
16
17
  import durabletask.internal.orchestrator_service_pb2 as pb
17
18
  import durabletask.internal.orchestrator_service_pb2_grpc as stubs
18
19
  import durabletask.internal.shared as shared
20
+ import durabletask.internal.tracing as tracing
19
21
  from durabletask import task
20
22
  from durabletask.internal.client_helpers import (
21
23
  build_query_entities_req,
@@ -176,14 +178,28 @@ class TaskHubGrpcClient:
176
178
  tags: Optional[dict[str, str]] = None,
177
179
  version: Optional[str] = None) -> str:
178
180
 
179
- req = build_schedule_new_orchestration_req(
180
- orchestrator, input=input, instance_id=instance_id, start_at=start_at,
181
- reuse_id_policy=reuse_id_policy, tags=tags,
182
- version=version if version else self.default_version)
183
-
184
- self._logger.info(f"Starting new '{req.name}' instance with ID = '{req.instanceId}'.")
185
- res: pb.CreateInstanceResponse = self._stub.StartInstance(req)
186
- return res.instanceId
181
+ name = orchestrator if isinstance(orchestrator, str) else task.get_name(orchestrator)
182
+ resolved_instance_id = instance_id if instance_id else uuid.uuid4().hex
183
+ resolved_version = version if version else self.default_version
184
+
185
+ with tracing.start_create_orchestration_span(
186
+ name, resolved_instance_id, version=resolved_version,
187
+ ):
188
+ req = build_schedule_new_orchestration_req(
189
+ orchestrator, input=input, instance_id=instance_id, start_at=start_at,
190
+ reuse_id_policy=reuse_id_policy, tags=tags,
191
+ version=version if version else self.default_version)
192
+
193
+ # Inject the active PRODUCER span context into the request so the sidecar
194
+ # stores it in the executionStarted event and the worker can parent all
195
+ # orchestration/activity/timer spans under this trace.
196
+ parent_trace_ctx = tracing.get_current_trace_context()
197
+ if parent_trace_ctx is not None:
198
+ req.parentTraceContext.CopyFrom(parent_trace_ctx)
199
+
200
+ self._logger.info(f"Starting new '{req.name}' instance with ID = '{req.instanceId}'.")
201
+ res: pb.CreateInstanceResponse = self._stub.StartInstance(req)
202
+ return res.instanceId
187
203
 
188
204
  def get_orchestration_state(self, instance_id: str, *, fetch_payloads: bool = True) -> Optional[OrchestrationState]:
189
205
  req = pb.GetInstanceRequest(instanceId=instance_id, getInputsAndOutputs=fetch_payloads)
@@ -245,10 +261,10 @@ class TaskHubGrpcClient:
245
261
 
246
262
  def raise_orchestration_event(self, instance_id: str, event_name: str, *,
247
263
  data: Optional[Any] = None) -> None:
248
- req = build_raise_event_req(instance_id, event_name, data)
249
-
250
- self._logger.info(f"Raising event '{event_name}' for instance '{instance_id}'.")
251
- self._stub.RaiseEvent(req)
264
+ with tracing.start_raise_event_span(event_name, instance_id):
265
+ req = build_raise_event_req(instance_id, event_name, data)
266
+ self._logger.info(f"Raising event '{event_name}' for instance '{instance_id}'.")
267
+ self._stub.RaiseEvent(req)
252
268
 
253
269
  def terminate_orchestration(self, instance_id: str, *,
254
270
  output: Optional[Any] = None,
@@ -418,14 +434,25 @@ class AsyncTaskHubGrpcClient:
418
434
  tags: Optional[dict[str, str]] = None,
419
435
  version: Optional[str] = None) -> str:
420
436
 
421
- req = build_schedule_new_orchestration_req(
422
- orchestrator, input=input, instance_id=instance_id, start_at=start_at,
423
- reuse_id_policy=reuse_id_policy, tags=tags,
424
- version=version if version else self.default_version)
437
+ name = orchestrator if isinstance(orchestrator, str) else task.get_name(orchestrator)
438
+ resolved_instance_id = instance_id if instance_id else uuid.uuid4().hex
439
+ resolved_version = version if version else self.default_version
425
440
 
426
- self._logger.info(f"Starting new '{req.name}' instance with ID = '{req.instanceId}'.")
427
- res: pb.CreateInstanceResponse = await self._stub.StartInstance(req)
428
- return res.instanceId
441
+ with tracing.start_create_orchestration_span(
442
+ name, resolved_instance_id, version=resolved_version,
443
+ ):
444
+ req = build_schedule_new_orchestration_req(
445
+ orchestrator, input=input, instance_id=instance_id, start_at=start_at,
446
+ reuse_id_policy=reuse_id_policy, tags=tags,
447
+ version=version if version else self.default_version)
448
+
449
+ parent_trace_ctx = tracing.get_current_trace_context()
450
+ if parent_trace_ctx is not None:
451
+ req.parentTraceContext.CopyFrom(parent_trace_ctx)
452
+
453
+ self._logger.info(f"Starting new '{req.name}' instance with ID = '{req.instanceId}'.")
454
+ res: pb.CreateInstanceResponse = await self._stub.StartInstance(req)
455
+ return res.instanceId
429
456
 
430
457
  async def get_orchestration_state(self, instance_id: str, *,
431
458
  fetch_payloads: bool = True) -> Optional[OrchestrationState]:
@@ -487,10 +514,10 @@ class AsyncTaskHubGrpcClient:
487
514
 
488
515
  async def raise_orchestration_event(self, instance_id: str, event_name: str, *,
489
516
  data: Optional[Any] = None) -> None:
490
- req = build_raise_event_req(instance_id, event_name, data)
491
-
492
- self._logger.info(f"Raising event '{event_name}' for instance '{instance_id}'.")
493
- await self._stub.RaiseEvent(req)
517
+ with tracing.start_raise_event_span(event_name, instance_id):
518
+ req = build_raise_event_req(instance_id, event_name, data)
519
+ self._logger.info(f"Raising event '{event_name}' for instance '{instance_id}'.")
520
+ await self._stub.RaiseEvent(req)
494
521
 
495
522
  async def terminate_orchestration(self, instance_id: str, *,
496
523
  output: Optional[Any] = None,
@@ -27,7 +27,8 @@ def new_orchestrator_completed_event() -> pb.HistoryEvent:
27
27
 
28
28
  def new_execution_started_event(name: str, instance_id: str, encoded_input: Optional[str] = None,
29
29
  tags: Optional[dict[str, str]] = None,
30
- version: Optional[str] = None) -> pb.HistoryEvent:
30
+ version: Optional[str] = None,
31
+ parent_trace_context: Optional[pb.TraceContext] = None) -> pb.HistoryEvent:
31
32
  return pb.HistoryEvent(
32
33
  eventId=-1,
33
34
  timestamp=timestamp_pb2.Timestamp(),
@@ -36,7 +37,8 @@ def new_execution_started_event(name: str, instance_id: str, encoded_input: Opti
36
37
  version=get_string_value(version),
37
38
  input=get_string_value(encoded_input),
38
39
  orchestrationInstance=pb.OrchestrationInstance(instanceId=instance_id),
39
- tags=tags))
40
+ tags=tags,
41
+ parentTraceContext=parent_trace_context))
40
42
 
41
43
 
42
44
  def new_timer_created_event(timer_id: int, fire_at: datetime) -> pb.HistoryEvent:
@@ -223,11 +225,13 @@ def new_create_timer_action(id: int, fire_at: datetime) -> pb.OrchestratorAction
223
225
 
224
226
 
225
227
  def new_schedule_task_action(id: int, name: str, encoded_input: Optional[str],
226
- tags: Optional[dict[str, str]]) -> pb.OrchestratorAction:
228
+ tags: Optional[dict[str, str]],
229
+ parent_trace_context: Optional[pb.TraceContext] = None) -> pb.OrchestratorAction:
227
230
  return pb.OrchestratorAction(id=id, scheduleTask=pb.ScheduleTaskAction(
228
231
  name=name,
229
232
  input=get_string_value(encoded_input),
230
- tags=tags
233
+ tags=tags,
234
+ parentTraceContext=parent_trace_context,
231
235
  ))
232
236
 
233
237
 
@@ -302,12 +306,14 @@ def new_create_sub_orchestration_action(
302
306
  name: str,
303
307
  instance_id: Optional[str],
304
308
  encoded_input: Optional[str],
305
- version: Optional[str]) -> pb.OrchestratorAction:
309
+ version: Optional[str],
310
+ parent_trace_context: Optional[pb.TraceContext] = None) -> pb.OrchestratorAction:
306
311
  return pb.OrchestratorAction(id=id, createSubOrchestration=pb.CreateSubOrchestrationAction(
307
312
  name=name,
308
313
  instanceId=instance_id,
309
314
  input=get_string_value(encoded_input),
310
- version=get_string_value(version)
315
+ version=get_string_value(version),
316
+ parentTraceContext=parent_trace_context,
311
317
  ))
312
318
 
313
319