durabletask 0.0.0.dev21__tar.gz → 0.0.0.dev22__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.
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/PKG-INFO +1 -1
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/client.py +6 -4
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/entities/durable_entity.py +5 -1
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/entities/entity_context.py +2 -1
- durabletask-0.0.0.dev22/durabletask/entities/entity_instance_id.py +89 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/entities/entity_metadata.py +1 -1
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/helpers.py +9 -2
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/task.py +21 -11
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/worker.py +23 -25
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/PKG-INFO +1 -1
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/pyproject.toml +1 -1
- durabletask-0.0.0.dev21/durabletask/entities/entity_instance_id.py +0 -42
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/LICENSE +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/README.md +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/__init__.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/entities/__init__.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/entities/entity_lock.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/entity_state_shim.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/exceptions.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/grpc_interceptor.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/orchestration_entity_context.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/orchestrator_service_pb2.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/orchestrator_service_pb2.pyi +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/orchestrator_service_pb2_grpc.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/proto_task_hub_sidecar_service_stub.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/shared.py +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/py.typed +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/SOURCES.txt +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/dependency_links.txt +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/requires.txt +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/top_level.txt +0 -0
- {durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/setup.cfg +0 -0
|
@@ -11,8 +11,7 @@ from typing import Any, Optional, Sequence, TypeVar, Union
|
|
|
11
11
|
import grpc
|
|
12
12
|
from google.protobuf import wrappers_pb2
|
|
13
13
|
|
|
14
|
-
from durabletask.entities import EntityInstanceId
|
|
15
|
-
from durabletask.entities.entity_metadata import EntityMetadata
|
|
14
|
+
from durabletask.entities import EntityInstanceId, EntityMetadata
|
|
16
15
|
import durabletask.internal.helpers as helpers
|
|
17
16
|
import durabletask.internal.orchestrator_service_pb2 as pb
|
|
18
17
|
import durabletask.internal.orchestrator_service_pb2_grpc as stubs
|
|
@@ -230,7 +229,10 @@ class TaskHubGrpcClient:
|
|
|
230
229
|
self._logger.info(f"Purging instance '{instance_id}'.")
|
|
231
230
|
self._stub.PurgeInstances(req)
|
|
232
231
|
|
|
233
|
-
def signal_entity(self,
|
|
232
|
+
def signal_entity(self,
|
|
233
|
+
entity_instance_id: EntityInstanceId[TInput, TOutput],
|
|
234
|
+
operation_name: str,
|
|
235
|
+
input: Optional[TInput] = None):
|
|
234
236
|
req = pb.SignalEntityRequest(
|
|
235
237
|
instanceId=str(entity_instance_id),
|
|
236
238
|
name=operation_name,
|
|
@@ -244,7 +246,7 @@ class TaskHubGrpcClient:
|
|
|
244
246
|
self._stub.SignalEntity(req, None) # TODO: Cancellation timeout?
|
|
245
247
|
|
|
246
248
|
def get_entity(self,
|
|
247
|
-
entity_instance_id: EntityInstanceId,
|
|
249
|
+
entity_instance_id: EntityInstanceId[Any, Any],
|
|
248
250
|
include_state: bool = True
|
|
249
251
|
) -> Optional[EntityMetadata]:
|
|
250
252
|
req = pb.GetEntityRequest(instanceId=str(entity_instance_id), includeState=include_state)
|
|
@@ -4,6 +4,7 @@ from durabletask.entities.entity_context import EntityContext
|
|
|
4
4
|
from durabletask.entities.entity_instance_id import EntityInstanceId
|
|
5
5
|
|
|
6
6
|
TState = TypeVar("TState")
|
|
7
|
+
TInput = TypeVar("TInput")
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class DurableEntity:
|
|
@@ -49,7 +50,10 @@ class DurableEntity:
|
|
|
49
50
|
"""
|
|
50
51
|
self.entity_context.set_state(state)
|
|
51
52
|
|
|
52
|
-
def signal_entity(self,
|
|
53
|
+
def signal_entity(self,
|
|
54
|
+
entity_instance_id: EntityInstanceId[TInput, Any],
|
|
55
|
+
operation: str,
|
|
56
|
+
input: Optional[TInput] = None) -> None:
|
|
53
57
|
"""Signal another entity to perform an operation.
|
|
54
58
|
|
|
55
59
|
Parameters
|
|
@@ -7,6 +7,7 @@ from durabletask.internal.entity_state_shim import StateShim
|
|
|
7
7
|
import durabletask.internal.orchestrator_service_pb2 as pb
|
|
8
8
|
|
|
9
9
|
TState = TypeVar("TState")
|
|
10
|
+
TInput = TypeVar("TInput")
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class EntityContext:
|
|
@@ -81,7 +82,7 @@ class EntityContext:
|
|
|
81
82
|
"""
|
|
82
83
|
self._state.set_state(new_state)
|
|
83
84
|
|
|
84
|
-
def signal_entity(self, entity_instance_id: EntityInstanceId, operation: str, input: Optional[
|
|
85
|
+
def signal_entity(self, entity_instance_id: EntityInstanceId[TInput, Any], operation: str, input: Optional[TInput] = None) -> None:
|
|
85
86
|
"""Signal another entity to perform an operation.
|
|
86
87
|
|
|
87
88
|
Parameters
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from typing import Any, Callable, TypeVar, Union, overload, TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
if TYPE_CHECKING:
|
|
4
|
+
from durabletask import task
|
|
5
|
+
from durabletask.entities.durable_entity import DurableEntity
|
|
6
|
+
from durabletask.entities.entity_context import EntityContext
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TInput = TypeVar('TInput')
|
|
10
|
+
TOutput = TypeVar('TOutput')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class EntityInstanceId[TInput, TOutput]:
|
|
14
|
+
@overload
|
|
15
|
+
def __new__(
|
|
16
|
+
cls,
|
|
17
|
+
entity: Callable[[EntityContext, TInput], TOutput],
|
|
18
|
+
key: str
|
|
19
|
+
) -> "EntityInstanceId[TInput, TOutput]": ...
|
|
20
|
+
|
|
21
|
+
@overload
|
|
22
|
+
def __new__(
|
|
23
|
+
cls,
|
|
24
|
+
entity: type[DurableEntity],
|
|
25
|
+
key: str
|
|
26
|
+
) -> "EntityInstanceId[Any, Any]": ...
|
|
27
|
+
|
|
28
|
+
@overload
|
|
29
|
+
def __new__(
|
|
30
|
+
cls,
|
|
31
|
+
entity: str,
|
|
32
|
+
key: str
|
|
33
|
+
) -> "EntityInstanceId[Any, Any]": ...
|
|
34
|
+
|
|
35
|
+
def __new__(
|
|
36
|
+
cls,
|
|
37
|
+
entity: Union[task.Entity[TInput, TOutput], str],
|
|
38
|
+
key: str
|
|
39
|
+
) -> "EntityInstanceId[Any, Any]":
|
|
40
|
+
return super().__new__(cls)
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
entity: Union[task.Entity[TInput, TOutput], str],
|
|
45
|
+
key: str
|
|
46
|
+
):
|
|
47
|
+
if not isinstance(entity, str):
|
|
48
|
+
from durabletask import task
|
|
49
|
+
entity = task.get_entity_name(entity)
|
|
50
|
+
self.entity: str = entity
|
|
51
|
+
self.key: str = key
|
|
52
|
+
|
|
53
|
+
def __str__(self) -> str:
|
|
54
|
+
return f"@{self.entity}@{self.key}"
|
|
55
|
+
|
|
56
|
+
def __eq__(self, other):
|
|
57
|
+
if not isinstance(other, EntityInstanceId):
|
|
58
|
+
return False
|
|
59
|
+
return self.entity == other.entity and self.key == other.key
|
|
60
|
+
|
|
61
|
+
def __lt__(self, other):
|
|
62
|
+
if not isinstance(other, EntityInstanceId):
|
|
63
|
+
return self < other
|
|
64
|
+
return str(self) < str(other)
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def parse(entity_id: str) -> "EntityInstanceId[Any, Any]":
|
|
68
|
+
"""Parse a string representation of an entity ID into an EntityInstanceId object.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
entity_id : str
|
|
73
|
+
The string representation of the entity ID, in the format '@entity@key'.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
EntityInstanceId
|
|
78
|
+
The parsed EntityInstanceId object.
|
|
79
|
+
|
|
80
|
+
Raises
|
|
81
|
+
------
|
|
82
|
+
ValueError
|
|
83
|
+
If the input string is not in the correct format.
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
_, entity, key = entity_id.split("@", 2)
|
|
87
|
+
return EntityInstanceId(entity=entity, key=key)
|
|
88
|
+
except ValueError as ex:
|
|
89
|
+
raise ValueError(f"Invalid entity ID format: {entity_id}", ex)
|
|
@@ -116,11 +116,18 @@ def new_sub_orchestration_failed_event(event_id: int, ex: Exception) -> pb.Histo
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def new_failure_details(ex: Exception) -> pb.TaskFailureDetails:
|
|
119
|
+
def new_failure_details(ex: Exception, _visited: Optional[set[int]] = None) -> pb.TaskFailureDetails:
|
|
120
|
+
if _visited is None:
|
|
121
|
+
_visited = set()
|
|
122
|
+
_visited.add(id(ex))
|
|
123
|
+
inner: Optional[BaseException] = ex.__cause__ or ex.__context__
|
|
124
|
+
if len(_visited) > 10 or (inner and id(inner) in _visited) or not isinstance(inner, Exception):
|
|
125
|
+
inner = None
|
|
120
126
|
return pb.TaskFailureDetails(
|
|
121
127
|
errorType=type(ex).__name__,
|
|
122
128
|
errorMessage=str(ex),
|
|
123
|
-
stackTrace=wrappers_pb2.StringValue(value=''.join(traceback.format_tb(ex.__traceback__)))
|
|
129
|
+
stackTrace=wrappers_pb2.StringValue(value=''.join(traceback.format_tb(ex.__traceback__))),
|
|
130
|
+
innerFailure=new_failure_details(inner, _visited) if inner else None
|
|
124
131
|
)
|
|
125
132
|
|
|
126
133
|
|
|
@@ -140,14 +140,14 @@ class OrchestrationContext(ABC):
|
|
|
140
140
|
|
|
141
141
|
@abstractmethod
|
|
142
142
|
def call_entity(self,
|
|
143
|
-
entity: EntityInstanceId,
|
|
143
|
+
entity: EntityInstanceId[TInput, TOutput],
|
|
144
144
|
operation: str,
|
|
145
|
-
input: Optional[TInput] = None) -> CompletableTask:
|
|
145
|
+
input: Optional[TInput] = None) -> CompletableTask[TOutput]:
|
|
146
146
|
"""Schedule entity function for execution.
|
|
147
147
|
|
|
148
148
|
Parameters
|
|
149
149
|
----------
|
|
150
|
-
entity: EntityInstanceId
|
|
150
|
+
entity: EntityInstanceId[TInput, TOutput]
|
|
151
151
|
The ID of the entity instance to call.
|
|
152
152
|
operation: str
|
|
153
153
|
The name of the operation to invoke on the entity.
|
|
@@ -164,7 +164,7 @@ class OrchestrationContext(ABC):
|
|
|
164
164
|
@abstractmethod
|
|
165
165
|
def signal_entity(
|
|
166
166
|
self,
|
|
167
|
-
entity_id: EntityInstanceId,
|
|
167
|
+
entity_id: EntityInstanceId[TInput, TOutput],
|
|
168
168
|
operation_name: str,
|
|
169
169
|
input: Optional[TInput] = None
|
|
170
170
|
) -> None:
|
|
@@ -172,7 +172,7 @@ class OrchestrationContext(ABC):
|
|
|
172
172
|
|
|
173
173
|
Parameters
|
|
174
174
|
----------
|
|
175
|
-
entity_id: EntityInstanceId
|
|
175
|
+
entity_id: EntityInstanceId[TInput, TOutput]
|
|
176
176
|
The ID of the entity instance to signal.
|
|
177
177
|
operation_name: str
|
|
178
178
|
The name of the operation to invoke on the entity.
|
|
@@ -182,7 +182,7 @@ class OrchestrationContext(ABC):
|
|
|
182
182
|
pass
|
|
183
183
|
|
|
184
184
|
@abstractmethod
|
|
185
|
-
def lock_entities(self, entities: list[EntityInstanceId]) -> CompletableTask[EntityLock]:
|
|
185
|
+
def lock_entities(self, entities: list[EntityInstanceId[Any, Any]]) -> CompletableTask[EntityLock]:
|
|
186
186
|
"""Creates a Task object that locks the specified entity instances.
|
|
187
187
|
|
|
188
188
|
The locks will be acquired the next time the orchestrator yields.
|
|
@@ -191,7 +191,7 @@ class OrchestrationContext(ABC):
|
|
|
191
191
|
|
|
192
192
|
Parameters
|
|
193
193
|
----------
|
|
194
|
-
entities: list[EntityInstanceId]
|
|
194
|
+
entities: list[EntityInstanceId[Any, Any]]
|
|
195
195
|
The list of entity instance IDs to lock.
|
|
196
196
|
|
|
197
197
|
Returns
|
|
@@ -302,8 +302,10 @@ class FailureDetails:
|
|
|
302
302
|
class TaskFailedError(Exception):
|
|
303
303
|
"""Exception type for all orchestration task failures."""
|
|
304
304
|
|
|
305
|
-
def __init__(self, message: str, details: pb.TaskFailureDetails):
|
|
305
|
+
def __init__(self, message: str, details: Union[pb.TaskFailureDetails, Exception]):
|
|
306
306
|
super().__init__(message)
|
|
307
|
+
if isinstance(details, Exception):
|
|
308
|
+
details = pbh.new_failure_details(details)
|
|
307
309
|
self._details = FailureDetails(
|
|
308
310
|
details.errorMessage,
|
|
309
311
|
details.errorType,
|
|
@@ -424,7 +426,7 @@ class CompletableTask(Task[T]):
|
|
|
424
426
|
if self._parent is not None:
|
|
425
427
|
self._parent.on_child_completed(self)
|
|
426
428
|
|
|
427
|
-
def fail(self, message: str, details: pb.TaskFailureDetails):
|
|
429
|
+
def fail(self, message: str, details: Union[Exception, pb.TaskFailureDetails]):
|
|
428
430
|
if self._is_complete:
|
|
429
431
|
raise ValueError('The task has already completed.')
|
|
430
432
|
self._exception = TaskFailedError(message, details)
|
|
@@ -536,8 +538,8 @@ class ActivityContext:
|
|
|
536
538
|
return self._task_id
|
|
537
539
|
|
|
538
540
|
|
|
539
|
-
# Orchestrators are generators that yield tasks and
|
|
540
|
-
Orchestrator = Callable[[OrchestrationContext, TInput], Union[Generator[Task, Any,
|
|
541
|
+
# Orchestrators are generators that yield tasks, recieve any type, and return TOutput
|
|
542
|
+
Orchestrator = Callable[[OrchestrationContext, TInput], Union[Generator[Task[Any], Any, TOutput], TOutput]]
|
|
541
543
|
|
|
542
544
|
# Activities are simple functions that can be scheduled by orchestrators
|
|
543
545
|
Activity = Callable[[ActivityContext, TInput], TOutput]
|
|
@@ -613,6 +615,14 @@ class RetryPolicy:
|
|
|
613
615
|
return self._retry_timeout
|
|
614
616
|
|
|
615
617
|
|
|
618
|
+
def get_entity_name(fn: Entity) -> str:
|
|
619
|
+
if hasattr(fn, "__durable_entity_name__"):
|
|
620
|
+
return getattr(fn, "__durable_entity_name__")
|
|
621
|
+
if isinstance(fn, type) and issubclass(fn, DurableEntity):
|
|
622
|
+
return fn.__name__
|
|
623
|
+
return get_name(fn)
|
|
624
|
+
|
|
625
|
+
|
|
616
626
|
def get_name(fn: Callable) -> str:
|
|
617
627
|
"""Returns the name of the provided function"""
|
|
618
628
|
name = fn.__name__
|
|
@@ -150,7 +150,7 @@ class _Registry:
|
|
|
150
150
|
self.entities = {}
|
|
151
151
|
self.entity_instances = {}
|
|
152
152
|
|
|
153
|
-
def add_orchestrator(self, fn: task.Orchestrator) -> str:
|
|
153
|
+
def add_orchestrator(self, fn: task.Orchestrator[TInput, TOutput]) -> str:
|
|
154
154
|
if fn is None:
|
|
155
155
|
raise ValueError("An orchestrator function argument is required.")
|
|
156
156
|
|
|
@@ -158,7 +158,7 @@ class _Registry:
|
|
|
158
158
|
self.add_named_orchestrator(name, fn)
|
|
159
159
|
return name
|
|
160
160
|
|
|
161
|
-
def add_named_orchestrator(self, name: str, fn: task.Orchestrator) -> None:
|
|
161
|
+
def add_named_orchestrator(self, name: str, fn: task.Orchestrator[TInput, TOutput]) -> None:
|
|
162
162
|
if not name:
|
|
163
163
|
raise ValueError("A non-empty orchestrator name is required.")
|
|
164
164
|
if name in self.orchestrators:
|
|
@@ -166,7 +166,7 @@ class _Registry:
|
|
|
166
166
|
|
|
167
167
|
self.orchestrators[name] = fn
|
|
168
168
|
|
|
169
|
-
def get_orchestrator(self, name: str) -> Optional[task.Orchestrator]:
|
|
169
|
+
def get_orchestrator(self, name: str) -> Optional[task.Orchestrator[Any, Any]]:
|
|
170
170
|
return self.orchestrators.get(name)
|
|
171
171
|
|
|
172
172
|
def add_activity(self, fn: task.Activity) -> str:
|
|
@@ -188,16 +188,13 @@ class _Registry:
|
|
|
188
188
|
def get_activity(self, name: str) -> Optional[task.Activity]:
|
|
189
189
|
return self.activities.get(name)
|
|
190
190
|
|
|
191
|
-
def add_entity(self, fn: task.Entity) -> str:
|
|
191
|
+
def add_entity(self, fn: task.Entity, name: Optional[str] = None) -> str:
|
|
192
192
|
if fn is None:
|
|
193
193
|
raise ValueError("An entity function argument is required.")
|
|
194
194
|
|
|
195
|
-
if
|
|
196
|
-
name = fn
|
|
197
|
-
|
|
198
|
-
else:
|
|
199
|
-
name = task.get_name(fn)
|
|
200
|
-
self.add_named_entity(name, fn)
|
|
195
|
+
if name is None:
|
|
196
|
+
name = task.get_entity_name(fn)
|
|
197
|
+
self.add_named_entity(name, fn)
|
|
201
198
|
return name
|
|
202
199
|
|
|
203
200
|
def add_named_entity(self, name: str, fn: task.Entity) -> None:
|
|
@@ -207,6 +204,7 @@ class _Registry:
|
|
|
207
204
|
raise ValueError(f"A '{name}' entity already exists.")
|
|
208
205
|
|
|
209
206
|
self.entities[name] = fn
|
|
207
|
+
setattr(fn, "__durable_entity_name__", name)
|
|
210
208
|
|
|
211
209
|
def get_entity(self, name: str) -> Optional[task.Entity]:
|
|
212
210
|
return self.entities.get(name)
|
|
@@ -362,7 +360,7 @@ class TaskHubGrpcWorker:
|
|
|
362
360
|
def __exit__(self, type, value, traceback):
|
|
363
361
|
self.stop()
|
|
364
362
|
|
|
365
|
-
def add_orchestrator(self, fn: task.Orchestrator) -> str:
|
|
363
|
+
def add_orchestrator(self, fn: task.Orchestrator[TInput, TOutput]) -> str:
|
|
366
364
|
"""Registers an orchestrator function with the worker."""
|
|
367
365
|
if self._is_running:
|
|
368
366
|
raise RuntimeError(
|
|
@@ -378,13 +376,13 @@ class TaskHubGrpcWorker:
|
|
|
378
376
|
)
|
|
379
377
|
return self._registry.add_activity(fn)
|
|
380
378
|
|
|
381
|
-
def add_entity(self, fn: task.Entity) -> str:
|
|
379
|
+
def add_entity(self, fn: task.Entity, name: Optional[str] = None) -> str:
|
|
382
380
|
"""Registers an entity function with the worker."""
|
|
383
381
|
if self._is_running:
|
|
384
382
|
raise RuntimeError(
|
|
385
383
|
"Entities cannot be added while the worker is running."
|
|
386
384
|
)
|
|
387
|
-
return self._registry.add_entity(fn)
|
|
385
|
+
return self._registry.add_entity(fn, name)
|
|
388
386
|
|
|
389
387
|
def use_versioning(self, version: VersioningOptions) -> None:
|
|
390
388
|
"""Initializes versioning options for sub-orchestrators and activities."""
|
|
@@ -1044,21 +1042,21 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
|
|
|
1044
1042
|
|
|
1045
1043
|
def call_entity(
|
|
1046
1044
|
self,
|
|
1047
|
-
entity: EntityInstanceId,
|
|
1045
|
+
entity: EntityInstanceId[TInput, TOutput],
|
|
1048
1046
|
operation: str,
|
|
1049
1047
|
input: Optional[TInput] = None,
|
|
1050
|
-
) -> task.CompletableTask:
|
|
1048
|
+
) -> task.CompletableTask[TOutput]:
|
|
1051
1049
|
id = self.next_sequence_number()
|
|
1052
1050
|
|
|
1053
1051
|
self.call_entity_function_helper(
|
|
1054
1052
|
id, entity, operation, input=input
|
|
1055
1053
|
)
|
|
1056
1054
|
|
|
1057
|
-
return self._pending_tasks.get(id, task.CompletableTask())
|
|
1055
|
+
return self._pending_tasks.get(id, task.CompletableTask[TOutput]())
|
|
1058
1056
|
|
|
1059
1057
|
def signal_entity(
|
|
1060
1058
|
self,
|
|
1061
|
-
entity_id: EntityInstanceId,
|
|
1059
|
+
entity_id: EntityInstanceId[TInput, TOutput],
|
|
1062
1060
|
operation_name: str,
|
|
1063
1061
|
input: Optional[TInput] = None
|
|
1064
1062
|
) -> None:
|
|
@@ -1068,7 +1066,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
|
|
|
1068
1066
|
id, entity_id, operation_name, input
|
|
1069
1067
|
)
|
|
1070
1068
|
|
|
1071
|
-
def lock_entities(self, entities: list[EntityInstanceId]) -> task.CompletableTask[EntityLock]:
|
|
1069
|
+
def lock_entities(self, entities: list[EntityInstanceId[Any, Any]]) -> task.CompletableTask[EntityLock]:
|
|
1072
1070
|
id = self.next_sequence_number()
|
|
1073
1071
|
|
|
1074
1072
|
self.lock_entities_function_helper(
|
|
@@ -1158,11 +1156,11 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
|
|
|
1158
1156
|
def call_entity_function_helper(
|
|
1159
1157
|
self,
|
|
1160
1158
|
id: Optional[int],
|
|
1161
|
-
entity_id: EntityInstanceId,
|
|
1159
|
+
entity_id: EntityInstanceId[TInput, TOutput],
|
|
1162
1160
|
operation: str,
|
|
1163
1161
|
*,
|
|
1164
1162
|
input: Optional[TInput] = None,
|
|
1165
|
-
):
|
|
1163
|
+
) -> None:
|
|
1166
1164
|
if id is None:
|
|
1167
1165
|
id = self.next_sequence_number()
|
|
1168
1166
|
|
|
@@ -1180,7 +1178,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
|
|
|
1180
1178
|
def signal_entity_function_helper(
|
|
1181
1179
|
self,
|
|
1182
1180
|
id: Optional[int],
|
|
1183
|
-
entity_id: EntityInstanceId,
|
|
1181
|
+
entity_id: EntityInstanceId[TInput, TOutput],
|
|
1184
1182
|
operation: str,
|
|
1185
1183
|
input: Optional[TInput]
|
|
1186
1184
|
) -> None:
|
|
@@ -1197,7 +1195,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
|
|
|
1197
1195
|
action = ph.new_signal_entity_action(id, entity_id, operation, encoded_input, self.new_uuid())
|
|
1198
1196
|
self._pending_actions[id] = action
|
|
1199
1197
|
|
|
1200
|
-
def lock_entities_function_helper(self, id: int, entities: list[EntityInstanceId]) -> None:
|
|
1198
|
+
def lock_entities_function_helper(self, id: int, entities: list[EntityInstanceId[Any, Any]]) -> None:
|
|
1201
1199
|
if id is None:
|
|
1202
1200
|
id = self.next_sequence_number()
|
|
1203
1201
|
|
|
@@ -1792,7 +1790,7 @@ class _OrchestrationExecutor:
|
|
|
1792
1790
|
# The orchestrator generator function completed
|
|
1793
1791
|
ctx.set_complete(generatorStopped.value, pb.ORCHESTRATION_STATUS_COMPLETED)
|
|
1794
1792
|
|
|
1795
|
-
def _parse_entity_event_sent_input(self, event: pb.HistoryEvent) -> Tuple[EntityInstanceId, str]:
|
|
1793
|
+
def _parse_entity_event_sent_input(self, event: pb.HistoryEvent) -> Tuple[EntityInstanceId[Any, Any], str]:
|
|
1796
1794
|
try:
|
|
1797
1795
|
entity_id = EntityInstanceId.parse(event.eventSent.instanceId)
|
|
1798
1796
|
except ValueError:
|
|
@@ -1806,7 +1804,7 @@ class _OrchestrationExecutor:
|
|
|
1806
1804
|
def _handle_entity_event_raised(self,
|
|
1807
1805
|
ctx: _RuntimeOrchestrationContext,
|
|
1808
1806
|
event: pb.HistoryEvent,
|
|
1809
|
-
entity_id: Optional[EntityInstanceId],
|
|
1807
|
+
entity_id: Optional[EntityInstanceId[Any, Any]],
|
|
1810
1808
|
task_id: Optional[int],
|
|
1811
1809
|
is_lock_event: bool):
|
|
1812
1810
|
# This eventRaised represents the result of an entity operation after being translated to the old
|
|
@@ -1919,7 +1917,7 @@ class _EntityExecutor:
|
|
|
1919
1917
|
def execute(
|
|
1920
1918
|
self,
|
|
1921
1919
|
orchestration_id: str,
|
|
1922
|
-
entity_id: EntityInstanceId,
|
|
1920
|
+
entity_id: EntityInstanceId[TInput, TOutput],
|
|
1923
1921
|
operation: str,
|
|
1924
1922
|
state: StateShim,
|
|
1925
1923
|
encoded_input: Optional[str],
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
class EntityInstanceId:
|
|
2
|
-
def __init__(self, entity: str, key: str):
|
|
3
|
-
self.entity = entity
|
|
4
|
-
self.key = key
|
|
5
|
-
|
|
6
|
-
def __str__(self) -> str:
|
|
7
|
-
return f"@{self.entity}@{self.key}"
|
|
8
|
-
|
|
9
|
-
def __eq__(self, other):
|
|
10
|
-
if not isinstance(other, EntityInstanceId):
|
|
11
|
-
return False
|
|
12
|
-
return self.entity == other.entity and self.key == other.key
|
|
13
|
-
|
|
14
|
-
def __lt__(self, other):
|
|
15
|
-
if not isinstance(other, EntityInstanceId):
|
|
16
|
-
return self < other
|
|
17
|
-
return str(self) < str(other)
|
|
18
|
-
|
|
19
|
-
@staticmethod
|
|
20
|
-
def parse(entity_id: str) -> "EntityInstanceId":
|
|
21
|
-
"""Parse a string representation of an entity ID into an EntityInstanceId object.
|
|
22
|
-
|
|
23
|
-
Parameters
|
|
24
|
-
----------
|
|
25
|
-
entity_id : str
|
|
26
|
-
The string representation of the entity ID, in the format '@entity@key'.
|
|
27
|
-
|
|
28
|
-
Returns
|
|
29
|
-
-------
|
|
30
|
-
EntityInstanceId
|
|
31
|
-
The parsed EntityInstanceId object.
|
|
32
|
-
|
|
33
|
-
Raises
|
|
34
|
-
------
|
|
35
|
-
ValueError
|
|
36
|
-
If the input string is not in the correct format.
|
|
37
|
-
"""
|
|
38
|
-
try:
|
|
39
|
-
_, entity, key = entity_id.split("@", 2)
|
|
40
|
-
return EntityInstanceId(entity=entity, key=key)
|
|
41
|
-
except ValueError as ex:
|
|
42
|
-
raise ValueError(f"Invalid entity ID format: {entity_id}", ex)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/entity_state_shim.py
RENAMED
|
File without changes
|
|
File without changes
|
{durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/grpc_interceptor.py
RENAMED
|
File without changes
|
|
File without changes
|
{durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask/internal/orchestrator_service_pb2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durabletask-0.0.0.dev21 → durabletask-0.0.0.dev22}/durabletask.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|