durabletask 1.1.0.dev2__tar.gz → 1.1.0.dev4__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 (30) hide show
  1. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/PKG-INFO +1 -1
  2. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/helpers.py +13 -4
  3. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/task.py +16 -0
  4. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/worker.py +17 -3
  5. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask.egg-info/PKG-INFO +1 -1
  6. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/pyproject.toml +1 -1
  7. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/LICENSE +0 -0
  8. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/README.md +0 -0
  9. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/__init__.py +0 -0
  10. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/client.py +0 -0
  11. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/__init__.py +0 -0
  12. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/durable_entity.py +0 -0
  13. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/entity_context.py +0 -0
  14. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/entity_instance_id.py +0 -0
  15. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/entity_lock.py +0 -0
  16. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/entities/entity_metadata.py +0 -0
  17. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/entity_state_shim.py +0 -0
  18. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/exceptions.py +0 -0
  19. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/grpc_interceptor.py +0 -0
  20. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/orchestration_entity_context.py +0 -0
  21. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/orchestrator_service_pb2.py +0 -0
  22. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/orchestrator_service_pb2.pyi +0 -0
  23. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/orchestrator_service_pb2_grpc.py +0 -0
  24. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/internal/shared.py +0 -0
  25. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask/py.typed +0 -0
  26. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask.egg-info/SOURCES.txt +0 -0
  27. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask.egg-info/dependency_links.txt +0 -0
  28. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask.egg-info/requires.txt +0 -0
  29. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/durabletask.egg-info/top_level.txt +0 -0
  30. {durabletask-1.1.0.dev2 → durabletask-1.1.0.dev4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: durabletask
3
- Version: 1.1.0.dev2
3
+ Version: 1.1.0.dev4
4
4
  Summary: A Durable Task Client SDK for Python
5
5
  License: MIT License
6
6
 
@@ -196,9 +196,14 @@ def new_schedule_task_action(id: int, name: str, encoded_input: Optional[str],
196
196
  ))
197
197
 
198
198
 
199
- def new_call_entity_action(id: int, parent_instance_id: str, entity_id: EntityInstanceId, operation: str, encoded_input: Optional[str]):
199
+ def new_call_entity_action(id: int,
200
+ parent_instance_id: str,
201
+ entity_id: EntityInstanceId,
202
+ operation: str,
203
+ encoded_input: Optional[str],
204
+ request_id: str) -> pb.OrchestratorAction:
200
205
  return pb.OrchestratorAction(id=id, sendEntityMessage=pb.SendEntityMessageAction(entityOperationCalled=pb.EntityOperationCalledEvent(
201
- requestId=f"{parent_instance_id}:{id}",
206
+ requestId=request_id,
202
207
  operation=operation,
203
208
  scheduledTime=None,
204
209
  input=get_string_value(encoded_input),
@@ -208,9 +213,13 @@ def new_call_entity_action(id: int, parent_instance_id: str, entity_id: EntityIn
208
213
  )))
209
214
 
210
215
 
211
- def new_signal_entity_action(id: int, entity_id: EntityInstanceId, operation: str, encoded_input: Optional[str]):
216
+ def new_signal_entity_action(id: int,
217
+ entity_id: EntityInstanceId,
218
+ operation: str,
219
+ encoded_input: Optional[str],
220
+ request_id: str) -> pb.OrchestratorAction:
212
221
  return pb.OrchestratorAction(id=id, sendEntityMessage=pb.SendEntityMessageAction(entityOperationSignaled=pb.EntityOperationSignaledEvent(
213
- requestId=f"{entity_id}:{id}",
222
+ requestId=request_id,
214
223
  operation=operation,
215
224
  scheduledTime=None,
216
225
  input=get_string_value(encoded_input),
@@ -259,6 +259,22 @@ class OrchestrationContext(ABC):
259
259
  """
260
260
  pass
261
261
 
262
+ @abstractmethod
263
+ def new_uuid(self) -> str:
264
+ """Create a new UUID that is safe for replay within an orchestration or operation.
265
+
266
+ The default implementation of this method creates a name-based UUID
267
+ using the algorithm from RFC 4122 §4.3. The name input used to generate
268
+ this value is a combination of the orchestration instance ID, the current UTC datetime,
269
+ and an internally managed counter.
270
+
271
+ Returns
272
+ -------
273
+ str
274
+ New UUID that is safe for replay within an orchestration or operation.
275
+ """
276
+ pass
277
+
262
278
  @abstractmethod
263
279
  def _exit_critical_section(self) -> None:
264
280
  pass
@@ -13,6 +13,7 @@ from threading import Event, Thread
13
13
  from types import GeneratorType
14
14
  from enum import Enum
15
15
  from typing import Any, Generator, Optional, Sequence, TypeVar, Union
16
+ import uuid
16
17
  from packaging.version import InvalidVersion, parse
17
18
 
18
19
  import grpc
@@ -33,6 +34,7 @@ from durabletask.internal.grpc_interceptor import DefaultClientInterceptorImpl
33
34
 
34
35
  TInput = TypeVar("TInput")
35
36
  TOutput = TypeVar("TOutput")
37
+ DATETIME_STRING_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
36
38
 
37
39
 
38
40
  class ConcurrencyOptions:
@@ -832,6 +834,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
832
834
  # Maps criticalSectionId to task ID
833
835
  self._entity_lock_id_map: dict[str, int] = {}
834
836
  self._sequence_number = 0
837
+ self._new_uuid_counter = 0
835
838
  self._current_utc_datetime = datetime(1000, 1, 1)
836
839
  self._instance_id = instance_id
837
840
  self._registry = registry
@@ -1166,7 +1169,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1166
1169
  raise RuntimeError(error_message)
1167
1170
 
1168
1171
  encoded_input = shared.to_json(input) if input is not None else None
1169
- action = ph.new_call_entity_action(id, self.instance_id, entity_id, operation, encoded_input)
1172
+ action = ph.new_call_entity_action(id, self.instance_id, entity_id, operation, encoded_input, self.new_uuid())
1170
1173
  self._pending_actions[id] = action
1171
1174
 
1172
1175
  fn_task = task.CompletableTask()
@@ -1189,7 +1192,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1189
1192
 
1190
1193
  encoded_input = shared.to_json(input) if input is not None else None
1191
1194
 
1192
- action = ph.new_signal_entity_action(id, entity_id, operation, encoded_input)
1195
+ action = ph.new_signal_entity_action(id, entity_id, operation, encoded_input, self.new_uuid())
1193
1196
  self._pending_actions[id] = action
1194
1197
 
1195
1198
  def lock_entities_function_helper(self, id: int, entities: list[EntityInstanceId]) -> None:
@@ -1200,7 +1203,7 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1200
1203
  if not transition_valid:
1201
1204
  raise RuntimeError(error_message)
1202
1205
 
1203
- critical_section_id = f"{self.instance_id}:{id:04x}"
1206
+ critical_section_id = self.new_uuid()
1204
1207
 
1205
1208
  request, target = self._entity_context.emit_acquire_message(critical_section_id, entities)
1206
1209
 
@@ -1252,6 +1255,17 @@ class _RuntimeOrchestrationContext(task.OrchestrationContext):
1252
1255
 
1253
1256
  self.set_continued_as_new(new_input, save_events)
1254
1257
 
1258
+ def new_uuid(self) -> str:
1259
+ NAMESPACE_UUID: str = "9e952958-5e33-4daf-827f-2fa12937b875"
1260
+
1261
+ uuid_name_value = \
1262
+ f"{self._instance_id}" \
1263
+ f"_{self.current_utc_datetime.strftime(DATETIME_STRING_FORMAT)}" \
1264
+ f"_{self._new_uuid_counter}"
1265
+ self._new_uuid_counter += 1
1266
+ namespace_uuid = uuid.uuid5(uuid.NAMESPACE_OID, NAMESPACE_UUID)
1267
+ return str(uuid.uuid5(namespace_uuid, uuid_name_value))
1268
+
1255
1269
 
1256
1270
  class ExecutionResults:
1257
1271
  actions: list[pb.OrchestratorAction]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: durabletask
3
- Version: 1.1.0.dev2
3
+ Version: 1.1.0.dev4
4
4
  Summary: A Durable Task Client SDK for Python
5
5
  License: MIT License
6
6
 
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
9
9
 
10
10
  [project]
11
11
  name = "durabletask"
12
- version = "1.1.0.dev2"
12
+ version = "1.1.0.dev4"
13
13
  description = "A Durable Task Client SDK for Python"
14
14
  keywords = [
15
15
  "durable",