dex-python-sdk 1.2.1__tar.gz → 1.4.1__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 (65) hide show
  1. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/PKG-INFO +13 -3
  2. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/README.md +12 -2
  3. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_invocation_context.py +5 -0
  4. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/context.py +13 -0
  5. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/pyproject.toml +1 -1
  6. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/LEGACY_NOTICES.md +0 -0
  7. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/LICENSE +0 -0
  8. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/__init__.py +0 -0
  9. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_async_value_hydrator.py +0 -0
  10. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_async_worker_dispatcher.py +0 -0
  11. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_async_worker_service.py +0 -0
  12. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_grpc_errors.py +0 -0
  13. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_native.pyi +0 -0
  14. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_server_protocol.py +0 -0
  15. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_utils.py +0 -0
  16. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_value_hydrator.py +0 -0
  17. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_value_mapper.py +0 -0
  18. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_worker_dispatcher.py +0 -0
  19. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/_worker_service.py +0 -0
  20. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/async_client.py +0 -0
  21. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/async_worker.py +0 -0
  22. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/attribute.py +0 -0
  23. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/attribute_match.py +0 -0
  24. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/blob_cache.py +0 -0
  25. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/channel.py +0 -0
  26. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/client.py +0 -0
  27. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/client_options.py +0 -0
  28. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/codec.py +0 -0
  29. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/condition.py +0 -0
  30. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/dexpb/__init__.py +0 -0
  31. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/dexpb/dex_pb2.py +0 -0
  32. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/dexpb/dex_pb2.pyi +0 -0
  33. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/dexpb/dex_pb2_grpc.py +0 -0
  34. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/flow.py +0 -0
  35. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/flow_config.py +0 -0
  36. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/flow_info.py +0 -0
  37. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/flow_options.py +0 -0
  38. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/flow_result.py +0 -0
  39. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/py.typed +0 -0
  40. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/rpc_invoke_options.py +0 -0
  41. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/runtime_errors.py +0 -0
  42. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/step.py +0 -0
  43. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/step_execution.py +0 -0
  44. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/stream.py +0 -0
  45. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/subflow.py +0 -0
  46. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/timer.py +0 -0
  47. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/wait.py +0 -0
  48. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/wait_options.py +0 -0
  49. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/worker.py +0 -0
  50. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/dex/worker_options.py +0 -0
  51. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/Cargo.lock +0 -0
  52. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/Cargo.toml +0 -0
  53. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/Cargo.toml +0 -0
  54. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/LICENSE +0 -0
  55. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/config.rs +0 -0
  56. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/entry.rs +0 -0
  57. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/error.rs +0 -0
  58. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/format.rs +0 -0
  59. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/lib.rs +0 -0
  60. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/policy.rs +0 -0
  61. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/src/store.rs +0 -0
  62. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache/tests/blob_cache_integration.rs +0 -0
  63. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache-python/Cargo.toml +0 -0
  64. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache-python/LICENSE +0 -0
  65. {dex_python_sdk-1.2.1 → dex_python_sdk-1.4.1}/sdk-rust/crates/dex-blob-cache-python/src/lib.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dex-python-sdk
3
- Version: 1.2.1
3
+ Version: 1.4.1
4
4
  Requires-Dist: grpcio>=1.83.0
5
5
  Requires-Dist: grpcio-status>=1.83.0
6
6
  Requires-Dist: protobuf>=7.35.1
@@ -444,12 +444,22 @@ Client calls raise concrete `DexServiceError` subclasses. Existing-Flow reads
444
444
  (`describe_flow`, `wait_for_flow`, and `time_travel`) raise
445
445
  `FlowNotFoundError` when the Flow does not exist. Mutations, RPCs, timer/Step
446
446
  waits, config updates, and continue-as-new triggers raise
447
- `FlowNotActiveError` when no running Flow can accept the operation.
447
+ `FlowNotActiveOrNotFoundError` when no running Flow can accept the operation.
448
+
449
+ RPCs also use this error when the target Flow cannot be found, including query-only
450
+ reads. A query-only RPC without locks, transactional execution, durable effects, or
451
+ Server-forced Update routing can read a retained terminal execution. At that confirmed
452
+ read boundary, this error means no readable target was found; return the application's
453
+ missing or unavailable result directly, without a lifecycle probe, a short timeout, a
454
+ retry, or historical Step-output decoding. Preserve other service and Worker failures.
455
+ For mutations and active-only RPCs, the error can mean either missing or closed and does
456
+ not prove that the requested action succeeded. RPC success does not prove that the Flow
457
+ is active.
448
458
 
449
459
  ```python
450
460
  try:
451
461
  client.invoke_rpc(orders.update_order, order_id, update)
452
- except dex.FlowNotActiveError:
462
+ except dex.FlowNotActiveOrNotFoundError:
453
463
  # The Flow is missing or already closed.
454
464
  pass
455
465
  ```
@@ -428,12 +428,22 @@ Client calls raise concrete `DexServiceError` subclasses. Existing-Flow reads
428
428
  (`describe_flow`, `wait_for_flow`, and `time_travel`) raise
429
429
  `FlowNotFoundError` when the Flow does not exist. Mutations, RPCs, timer/Step
430
430
  waits, config updates, and continue-as-new triggers raise
431
- `FlowNotActiveError` when no running Flow can accept the operation.
431
+ `FlowNotActiveOrNotFoundError` when no running Flow can accept the operation.
432
+
433
+ RPCs also use this error when the target Flow cannot be found, including query-only
434
+ reads. A query-only RPC without locks, transactional execution, durable effects, or
435
+ Server-forced Update routing can read a retained terminal execution. At that confirmed
436
+ read boundary, this error means no readable target was found; return the application's
437
+ missing or unavailable result directly, without a lifecycle probe, a short timeout, a
438
+ retry, or historical Step-output decoding. Preserve other service and Worker failures.
439
+ For mutations and active-only RPCs, the error can mean either missing or closed and does
440
+ not prove that the requested action succeeded. RPC success does not prove that the Flow
441
+ is active.
432
442
 
433
443
  ```python
434
444
  try:
435
445
  client.invoke_rpc(orders.update_order, order_id, update)
436
- except dex.FlowNotActiveError:
446
+ except dex.FlowNotActiveOrNotFoundError:
437
447
  # The Flow is missing or already closed.
438
448
  pass
439
449
  ```
@@ -8,6 +8,7 @@
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
+ from datetime import UTC, datetime
11
12
  from enum import Enum
12
13
  from typing import Any, Callable, Protocol, Sequence, TypeVar, cast
13
14
  from urllib.parse import unquote
@@ -126,6 +127,10 @@ class InvocationContext:
126
127
  error_type=self._metadata.recovery_error.error_type,
127
128
  )
128
129
 
130
+ @property
131
+ def first_attempt_at(self) -> datetime:
132
+ return datetime.fromtimestamp(self._metadata.first_attempt_timestamp, UTC)
133
+
129
134
  @property
130
135
  def attempt(self) -> int:
131
136
  return self._metadata.attempt
@@ -11,6 +11,7 @@
11
11
  from __future__ import annotations
12
12
 
13
13
  from dataclasses import dataclass
14
+ from datetime import datetime
14
15
  from typing import TYPE_CHECKING, Any, Protocol, Sequence, TypeVar
15
16
 
16
17
  if TYPE_CHECKING:
@@ -95,6 +96,18 @@ class Context(Protocol):
95
96
  """
96
97
  ...
97
98
 
99
+ @property
100
+ def first_attempt_at(self) -> datetime:
101
+ """Return when the first attempt of this handler invocation started.
102
+
103
+ The value is stable across retries of the same invocation, so a handler
104
+ can derive a deadline that a retry does not reset.
105
+
106
+ Returns:
107
+ A timezone-aware UTC time with one-second precision.
108
+ """
109
+ ...
110
+
98
111
  @property
99
112
  def attempt(self) -> int:
100
113
  """Return the one-based handler retry attempt.
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "dex-python-sdk"
3
3
  # Publish uses tag sdk-python/v*; CI stamps this for release builds.
4
- version = "1.2.1"
4
+ version = "1.4.1"
5
5
  description = "Python SDK for the Dex workflow engine"
6
6
  authors = [{name = "Super Durable"}]
7
7
  readme = "README.md"
File without changes