durabletask 0.0.0.dev4__tar.gz → 0.0.0.dev6__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 (31) hide show
  1. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/PKG-INFO +1 -1
  2. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/entity_instance_id.py +7 -5
  3. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/entity_metadata.py +3 -2
  4. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/helpers.py +4 -3
  5. durabletask-0.0.0.dev6/durabletask/py.typed +0 -0
  6. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/task.py +4 -3
  7. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/worker.py +65 -56
  8. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask.egg-info/PKG-INFO +1 -1
  9. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask.egg-info/SOURCES.txt +1 -1
  10. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/pyproject.toml +1 -1
  11. durabletask-0.0.0.dev4/durabletask/internal/proto_task_hub_sidecar_service_stub.py +0 -34
  12. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/LICENSE +0 -0
  13. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/README.md +0 -0
  14. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/__init__.py +0 -0
  15. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/client.py +0 -0
  16. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/__init__.py +0 -0
  17. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/durable_entity.py +0 -0
  18. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/entity_context.py +0 -0
  19. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/entities/entity_lock.py +0 -0
  20. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/entity_state_shim.py +0 -0
  21. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/exceptions.py +0 -0
  22. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/grpc_interceptor.py +0 -0
  23. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/orchestration_entity_context.py +0 -0
  24. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/orchestrator_service_pb2.py +0 -0
  25. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/orchestrator_service_pb2.pyi +0 -0
  26. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/orchestrator_service_pb2_grpc.py +0 -0
  27. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask/internal/shared.py +0 -0
  28. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask.egg-info/dependency_links.txt +0 -0
  29. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask.egg-info/requires.txt +0 -0
  30. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/durabletask.egg-info/top_level.txt +0 -0
  31. {durabletask-0.0.0.dev4 → durabletask-0.0.0.dev6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: durabletask
3
- Version: 0.0.0.dev4
3
+ Version: 0.0.0.dev6
4
4
  Summary: A Durable Task Client SDK for Python
5
5
  License: MIT License
6
6
 
@@ -1,6 +1,3 @@
1
- from typing import Optional
2
-
3
-
4
1
  class EntityInstanceId:
5
2
  def __init__(self, entity: str, key: str):
6
3
  self.entity = entity
@@ -30,8 +27,13 @@ class EntityInstanceId:
30
27
 
31
28
  Returns
32
29
  -------
33
- Optional[EntityInstanceId]
34
- The parsed EntityInstanceId object, or None if the input is None.
30
+ EntityInstanceId
31
+ The parsed EntityInstanceId object.
32
+
33
+ Raises
34
+ ------
35
+ ValueError
36
+ If the input string is not in the correct format.
35
37
  """
36
38
  try:
37
39
  _, entity, key = entity_id.split("@", 2)
@@ -44,8 +44,9 @@ class EntityMetadata:
44
44
 
45
45
  @staticmethod
46
46
  def from_entity_response(entity_response: pb.GetEntityResponse, includes_state: bool):
47
- entity_id = EntityInstanceId.parse(entity_response.entity.instanceId)
48
- if not entity_id:
47
+ try:
48
+ entity_id = EntityInstanceId.parse(entity_response.entity.instanceId)
49
+ except ValueError:
49
50
  raise ValueError("Invalid entity instance ID in entity response.")
50
51
  entity_state = None
51
52
  if includes_state:
@@ -199,8 +199,9 @@ def new_schedule_task_action(id: int, name: str, encoded_input: Optional[str],
199
199
  def new_call_entity_action(id: int,
200
200
  parent_instance_id: str,
201
201
  entity_id: EntityInstanceId,
202
- operation: str, encoded_input: Optional[str],
203
- request_id: str):
202
+ operation: str,
203
+ encoded_input: Optional[str],
204
+ request_id: str) -> pb.OrchestratorAction:
204
205
  return pb.OrchestratorAction(id=id, sendEntityMessage=pb.SendEntityMessageAction(entityOperationCalled=pb.EntityOperationCalledEvent(
205
206
  requestId=request_id,
206
207
  operation=operation,
@@ -216,7 +217,7 @@ def new_signal_entity_action(id: int,
216
217
  entity_id: EntityInstanceId,
217
218
  operation: str,
218
219
  encoded_input: Optional[str],
219
- request_id: str):
220
+ request_id: str) -> pb.OrchestratorAction:
220
221
  return pb.OrchestratorAction(id=id, sendEntityMessage=pb.SendEntityMessageAction(entityOperationSignaled=pb.EntityOperationSignaledEvent(
221
222
  requestId=request_id,
222
223
  operation=operation,
File without changes
@@ -139,7 +139,8 @@ class OrchestrationContext(ABC):
139
139
  pass
140
140
 
141
141
  @abstractmethod
142
- def call_entity(self, entity: EntityInstanceId,
142
+ def call_entity(self,
143
+ entity: EntityInstanceId,
143
144
  operation: str,
144
145
  input: Optional[TInput] = None) -> Task:
145
146
  """Schedule entity function for execution.
@@ -264,8 +265,8 @@ class OrchestrationContext(ABC):
264
265
 
265
266
  The default implementation of this method creates a name-based UUID
266
267
  using the algorithm from RFC 4122 §4.3. The name input used to generate
267
- this value is a combination of the orchestration instance ID and an
268
- internally managed sequence number.
268
+ this value is a combination of the orchestration instance ID, the current UTC datetime,
269
+ and an internally managed counter.
269
270
 
270
271
  Returns
271
272
  -------
@@ -12,7 +12,7 @@ from datetime import datetime, timedelta, timezone
12
12
  from threading import Event, Thread
13
13
  from types import GeneratorType
14
14
  from enum import Enum
15
- from typing import Any, Generator, Optional, Sequence, TypeVar, Union
15
+ from typing import Any, Generator, Optional, Sequence, Tuple, TypeVar, Union
16
16
  import uuid
17
17
  from packaging.version import InvalidVersion, parse
18
18
 
@@ -20,7 +20,6 @@ import grpc
20
20
  from google.protobuf import empty_pb2
21
21
 
22
22
  from durabletask.internal import helpers
23
- from durabletask.internal.proto_task_hub_sidecar_service_stub import ProtoTaskHubSidecarServiceStub
24
23
  from durabletask.internal.entity_state_shim import StateShim
25
24
  from durabletask.internal.helpers import new_timestamp
26
25
  from durabletask.entities import DurableEntity, EntityLock, EntityInstanceId, EntityContext
@@ -632,7 +631,7 @@ class TaskHubGrpcWorker:
632
631
  def _execute_orchestrator(
633
632
  self,
634
633
  req: pb.OrchestratorRequest,
635
- stub: Union[stubs.TaskHubSidecarServiceStub, ProtoTaskHubSidecarServiceStub],
634
+ stub: stubs.TaskHubSidecarServiceStub,
636
635
  completionToken,
637
636
  ):
638
637
  try:
@@ -739,10 +738,9 @@ class TaskHubGrpcWorker:
739
738
  def _execute_entity_batch(
740
739
  self,
741
740
  req: Union[pb.EntityBatchRequest, pb.EntityRequest],
742
- stub: Union[stubs.TaskHubSidecarServiceStub, ProtoTaskHubSidecarServiceStub],
741
+ stub: stubs.TaskHubSidecarServiceStub,
743
742
  completionToken,
744
743
  ):
745
- operation_infos = None
746
744
  if isinstance(req, pb.EntityRequest):
747
745
  req, operation_infos = helpers.convert_to_entity_batch_request(req)
748
746
 
@@ -754,9 +752,10 @@ class TaskHubGrpcWorker:
754
752
  for operation in req.operations:
755
753
  start_time = datetime.now(timezone.utc)
756
754
  executor = _EntityExecutor(self._registry, self._logger)
757
- entity_instance_id = EntityInstanceId.parse(instance_id)
758
- if not entity_instance_id:
759
- raise RuntimeError(f"Invalid entity instance ID '{operation.requestId}' in entity operation request.")
755
+ try:
756
+ entity_instance_id = EntityInstanceId.parse(instance_id)
757
+ except ValueError:
758
+ raise RuntimeError(f"Invalid entity instance ID '{instance_id}' in entity operation request.")
760
759
 
761
760
  operation_result = None
762
761
 
@@ -798,7 +797,7 @@ class TaskHubGrpcWorker:
798
797
  stub.CompleteEntityTask(batch_result)
799
798
  except Exception as ex:
800
799
  self._logger.exception(
801
- f"Failed to deliver entity response for orchestration ID '{instance_id}' to sidecar: {ex}"
800
+ f"Failed to deliver entity response for '{entity_instance_id}' of orchestration ID '{instance_id}' to sidecar: {ex}"
802
801
  )
803
802
 
804
803
  # TODO: Reset context
@@ -831,7 +830,8 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
831
830
  self._pending_actions: dict[int, pb.OrchestratorAction] = {}
832
831
  self._pending_tasks: dict[int, task.CompletableTask] = {}
833
832
  # Maps entity ID to task ID
834
- self._entity_task_id_map: dict[str, tuple[EntityInstanceId, int, Optional[str]]] = {}
833
+ self._entity_task_id_map: dict[str, tuple[EntityInstanceId, int]] = {}
834
+ self._entity_lock_task_id_map: dict[str, tuple[EntityInstanceId, int]] = {}
835
835
  # Maps criticalSectionId to task ID
836
836
  self._entity_lock_id_map: dict[str, int] = {}
837
837
  self._sequence_number = 0
@@ -1170,12 +1170,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1170
1170
  raise RuntimeError(error_message)
1171
1171
 
1172
1172
  encoded_input = shared.to_json(input) if input is not None else None
1173
- action = ph.new_call_entity_action(id,
1174
- self.instance_id,
1175
- entity_id,
1176
- operation,
1177
- encoded_input,
1178
- self.new_uuid())
1173
+ action = ph.new_call_entity_action(id, self.instance_id, entity_id, operation, encoded_input, self.new_uuid())
1179
1174
  self._pending_actions[id] = action
1180
1175
 
1181
1176
  fn_task = task.CompletableTask()
@@ -1262,14 +1257,14 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1262
1257
  self.set_continued_as_new(new_input, save_events)
1263
1258
 
1264
1259
  def new_uuid(self) -> str:
1265
- URL_NAMESPACE: str = "9e952958-5e33-4daf-827f-2fa12937b875"
1260
+ NAMESPACE_UUID: str = "9e952958-5e33-4daf-827f-2fa12937b875"
1266
1261
 
1267
1262
  uuid_name_value = \
1268
1263
  f"{self._instance_id}" \
1269
1264
  f"_{self.current_utc_datetime.strftime(DATETIME_STRING_FORMAT)}" \
1270
1265
  f"_{self._new_uuid_counter}"
1271
1266
  self._new_uuid_counter += 1
1272
- namespace_uuid = uuid.uuid5(uuid.NAMESPACE_OID, URL_NAMESPACE)
1267
+ namespace_uuid = uuid.uuid5(uuid.NAMESPACE_OID, NAMESPACE_UUID)
1273
1268
  return str(uuid.uuid5(namespace_uuid, uuid_name_value))
1274
1269
 
1275
1270
 
@@ -1612,32 +1607,11 @@ class _OrchestrationExecutor:
1612
1607
  raise TypeError("Unexpected sub-orchestration task type")
1613
1608
  elif event.HasField("eventRaised"):
1614
1609
  if event.eventRaised.name in ctx._entity_task_id_map:
1615
- # This eventRaised represents the result of an entity operation after being translated to the old
1616
- # entity protocol by the Durable WebJobs extension
1617
- entity_id, task_id, action_type = ctx._entity_task_id_map.get(event.eventRaised.name, (None, None, None))
1618
- if entity_id is None:
1619
- raise RuntimeError(f"Could not retrieve entity ID for entity-related eventRaised with ID '{event.eventId}'")
1620
- if task_id is None:
1621
- raise RuntimeError(f"Could not retrieve task ID for entity-related eventRaised with ID '{event.eventId}'")
1622
- entity_task = ctx._pending_tasks.pop(task_id, None)
1623
- if not entity_task:
1624
- raise RuntimeError(f"Could not retrieve entity task for entity-related eventRaised with ID '{event.eventId}'")
1625
- result = None
1626
- if not ph.is_empty(event.eventRaised.input):
1627
- # TODO: Investigate why the event result is wrapped in a dict with "result" key
1628
- result = shared.from_json(event.eventRaised.input.value)["result"]
1629
- if action_type == "entityOperationCalled":
1630
- ctx._entity_context.recover_lock_after_call(entity_id)
1631
- entity_task.complete(result)
1632
- ctx.resume()
1633
- elif action_type == "entityLockRequested":
1634
- ctx._entity_context.complete_acquire(event.eventRaised.name)
1635
- entity_task.complete(EntityLock(ctx))
1636
- ctx.resume()
1637
- else:
1638
- raise RuntimeError(f"Unknown action type '{action_type}' for entity-related eventRaised "
1639
- f"with ID '{event.eventId}'")
1640
-
1610
+ entity_id, task_id = ctx._entity_task_id_map.get(event.eventRaised.name, (None, None))
1611
+ self._handle_entity_event_raised(ctx, event, entity_id, task_id, False)
1612
+ elif event.eventRaised.name in ctx._entity_lock_task_id_map:
1613
+ entity_id, task_id = ctx._entity_lock_task_id_map.get(event.eventRaised.name, (None, None))
1614
+ self._handle_entity_event_raised(ctx, event, entity_id, task_id, True)
1641
1615
  else:
1642
1616
  # event names are case-insensitive
1643
1617
  event_name = event.eventRaised.name.casefold()
@@ -1705,10 +1679,11 @@ class _OrchestrationExecutor:
1705
1679
  raise _get_wrong_action_type_error(
1706
1680
  entity_call_id, expected_method_name, action
1707
1681
  )
1708
- entity_id = EntityInstanceId.parse(event.entityOperationCalled.targetInstanceId.value)
1709
- if not entity_id:
1682
+ try:
1683
+ entity_id = EntityInstanceId.parse(event.entityOperationCalled.targetInstanceId.value)
1684
+ except ValueError:
1710
1685
  raise RuntimeError(f"Could not parse entity ID from targetInstanceId '{event.entityOperationCalled.targetInstanceId.value}'")
1711
- ctx._entity_task_id_map[event.entityOperationCalled.requestId] = (entity_id, entity_call_id, None)
1686
+ ctx._entity_task_id_map[event.entityOperationCalled.requestId] = (entity_id, entity_call_id)
1712
1687
  elif event.HasField("entityOperationSignaled"):
1713
1688
  # This history event confirms that the entity signal was successfully scheduled.
1714
1689
  # Remove the entityOperationSignaled event from the pending action list so we don't schedule it
@@ -1769,7 +1744,7 @@ class _OrchestrationExecutor:
1769
1744
  ctx.resume()
1770
1745
  elif event.HasField("entityOperationCompleted"):
1771
1746
  request_id = event.entityOperationCompleted.requestId
1772
- entity_id, task_id, _ = ctx._entity_task_id_map.pop(request_id, (None, None, None))
1747
+ entity_id, task_id = ctx._entity_task_id_map.pop(request_id, (None, None))
1773
1748
  if not entity_id:
1774
1749
  raise RuntimeError(f"Could not parse entity ID from request ID '{request_id}'")
1775
1750
  if not task_id:
@@ -1802,15 +1777,11 @@ class _OrchestrationExecutor:
1802
1777
  action = ctx._pending_actions.pop(event.eventId, None)
1803
1778
  if action and action.HasField("sendEntityMessage"):
1804
1779
  if action.sendEntityMessage.HasField("entityOperationCalled"):
1805
- action_type = "entityOperationCalled"
1780
+ entity_id, event_id = self._parse_entity_event_sent_input(event)
1781
+ ctx._entity_task_id_map[event_id] = (entity_id, event.eventId)
1806
1782
  elif action.sendEntityMessage.HasField("entityLockRequested"):
1807
- action_type = "entityLockRequested"
1808
- else:
1809
- return
1810
-
1811
- entity_id = EntityInstanceId.parse(event.eventSent.instanceId)
1812
- event_id = json.loads(event.eventSent.input.value)["id"]
1813
- ctx._entity_task_id_map[event_id] = (entity_id, event.eventId, action_type)
1783
+ entity_id, event_id = self._parse_entity_event_sent_input(event)
1784
+ ctx._entity_lock_task_id_map[event_id] = (entity_id, event.eventId)
1814
1785
  else:
1815
1786
  eventType = event.WhichOneof("eventType")
1816
1787
  raise task.OrchestrationStateError(
@@ -1820,6 +1791,44 @@ class _OrchestrationExecutor:
1820
1791
  # The orchestrator generator function completed
1821
1792
  ctx.set_complete(generatorStopped.value, pb.ORCHESTRATION_STATUS_COMPLETED)
1822
1793
 
1794
+ def _parse_entity_event_sent_input(self, event: pb.HistoryEvent) -> Tuple[EntityInstanceId, str]:
1795
+ try:
1796
+ entity_id = EntityInstanceId.parse(event.eventSent.instanceId)
1797
+ except ValueError:
1798
+ raise RuntimeError(f"Could not parse entity ID from instanceId '{event.eventSent.instanceId}'")
1799
+ try:
1800
+ event_id = json.loads(event.eventSent.input.value)["id"]
1801
+ except (json.JSONDecodeError, KeyError, TypeError) as ex:
1802
+ raise RuntimeError(f"Could not parse event ID from eventSent input '{event.eventSent.input.value}'") from ex
1803
+ return entity_id, event_id
1804
+
1805
+ def _handle_entity_event_raised(self,
1806
+ ctx: _RuntimeOrchestrationContext,
1807
+ event: pb.HistoryEvent,
1808
+ entity_id: Optional[EntityInstanceId],
1809
+ task_id: Optional[int],
1810
+ is_lock_event: bool):
1811
+ # This eventRaised represents the result of an entity operation after being translated to the old
1812
+ # entity protocol by the Durable WebJobs extension
1813
+ if entity_id is None:
1814
+ raise RuntimeError(f"Could not retrieve entity ID for entity-related eventRaised with ID '{event.eventId}'")
1815
+ if task_id is None:
1816
+ raise RuntimeError(f"Could not retrieve task ID for entity-related eventRaised with ID '{event.eventId}'")
1817
+ entity_task = ctx._pending_tasks.pop(task_id, None)
1818
+ if not entity_task:
1819
+ raise RuntimeError(f"Could not retrieve entity task for entity-related eventRaised with ID '{event.eventId}'")
1820
+ result = None
1821
+ if not ph.is_empty(event.eventRaised.input):
1822
+ # TODO: Investigate why the event result is wrapped in a dict with "result" key
1823
+ result = shared.from_json(event.eventRaised.input.value)["result"]
1824
+ if is_lock_event:
1825
+ ctx._entity_context.complete_acquire(event.eventRaised.name)
1826
+ entity_task.complete(EntityLock(ctx))
1827
+ else:
1828
+ ctx._entity_context.recover_lock_after_call(entity_id)
1829
+ entity_task.complete(result)
1830
+ ctx.resume()
1831
+
1823
1832
  def evaluate_orchestration_versioning(self, versioning: Optional[VersioningOptions], orchestration_version: Optional[str]) -> Optional[pb.TaskFailureDetails]:
1824
1833
  if versioning is None:
1825
1834
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: durabletask
3
- Version: 0.0.0.dev4
3
+ Version: 0.0.0.dev6
4
4
  Summary: A Durable Task Client SDK for Python
5
5
  License: MIT License
6
6
 
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  durabletask/__init__.py
5
5
  durabletask/client.py
6
+ durabletask/py.typed
6
7
  durabletask/task.py
7
8
  durabletask/worker.py
8
9
  durabletask.egg-info/PKG-INFO
@@ -24,5 +25,4 @@ durabletask/internal/orchestration_entity_context.py
24
25
  durabletask/internal/orchestrator_service_pb2.py
25
26
  durabletask/internal/orchestrator_service_pb2.pyi
26
27
  durabletask/internal/orchestrator_service_pb2_grpc.py
27
- durabletask/internal/proto_task_hub_sidecar_service_stub.py
28
28
  durabletask/internal/shared.py
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
9
9
 
10
10
  [project]
11
11
  name = "durabletask"
12
- version = "0.0.0.dev4"
12
+ version = "0.0.0.dev6"
13
13
  description = "A Durable Task Client SDK for Python"
14
14
  keywords = [
15
15
  "durable",
@@ -1,34 +0,0 @@
1
- from typing import Any, Callable, Protocol
2
-
3
-
4
- class ProtoTaskHubSidecarServiceStub(Protocol):
5
- """A stub class roughly matching the TaskHubSidecarServiceStub generated from the .proto file.
6
- Used by Azure Functions during orchestration and entity executions to inject custom behavior,
7
- as no real sidecar stub is available.
8
- """
9
- Hello: Callable[..., Any]
10
- StartInstance: Callable[..., Any]
11
- GetInstance: Callable[..., Any]
12
- RewindInstance: Callable[..., Any]
13
- WaitForInstanceStart: Callable[..., Any]
14
- WaitForInstanceCompletion: Callable[..., Any]
15
- RaiseEvent: Callable[..., Any]
16
- TerminateInstance: Callable[..., Any]
17
- SuspendInstance: Callable[..., Any]
18
- ResumeInstance: Callable[..., Any]
19
- QueryInstances: Callable[..., Any]
20
- PurgeInstances: Callable[..., Any]
21
- GetWorkItems: Callable[..., Any]
22
- CompleteActivityTask: Callable[..., Any]
23
- CompleteOrchestratorTask: Callable[..., Any]
24
- CompleteEntityTask: Callable[..., Any]
25
- StreamInstanceHistory: Callable[..., Any]
26
- CreateTaskHub: Callable[..., Any]
27
- DeleteTaskHub: Callable[..., Any]
28
- SignalEntity: Callable[..., Any]
29
- GetEntity: Callable[..., Any]
30
- QueryEntities: Callable[..., Any]
31
- CleanEntityStorage: Callable[..., Any]
32
- AbandonTaskActivityWorkItem: Callable[..., Any]
33
- AbandonTaskOrchestratorWorkItem: Callable[..., Any]
34
- AbandonTaskEntityWorkItem: Callable[..., Any]