dex-python-sdk 1.23.0__tar.gz → 1.26.0__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.
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/PKG-INFO +27 -32
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/README.md +26 -31
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/__init__.py +1 -2
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_grpc_errors.py +1 -18
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_pull_worker.py +15 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_worker_dispatcher.py +4 -8
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/async_client.py +12 -22
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/async_worker.py +33 -106
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/client.py +10 -23
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/client_options.py +1 -5
- dex_python_sdk-1.26.0/dex/dexpb/dex_pb2.py +417 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/dexpb/dex_pb2.pyi +6 -621
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/dexpb/dex_pb2_grpc.py +64 -277
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/flow_config.py +2 -5
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/pull_registration.py +1 -1
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/runtime_errors.py +1 -1
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/worker.py +35 -124
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/worker_options.py +13 -70
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/pyproject.toml +1 -1
- dex_python_sdk-1.23.0/dex/_async_worker_service.py +0 -122
- dex_python_sdk-1.23.0/dex/_worker_service.py +0 -94
- dex_python_sdk-1.23.0/dex/dexpb/dex_pb2.py +0 -551
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/LEGACY_NOTICES.md +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/LICENSE +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_async_value_hydrator.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_async_worker_dispatcher.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_credential_transport.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_invocation_context.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_native.pyi +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_server_protocol.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_utils.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_value_hydrator.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/_value_mapper.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/attribute.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/attribute_match.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/blob_cache.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/channel.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/codec.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/condition.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/context.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/credential.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/dexpb/__init__.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/flow.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/flow_info.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/flow_options.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/flow_result.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/py.typed +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/rpc_invoke_options.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/step.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/step_execution.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/stream.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/subflow.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/timer.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/wait.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/dex/wait_options.py +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/Cargo.lock +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/Cargo.toml +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/Cargo.toml +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/LICENSE +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/README.md +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/config.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/entry.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/error.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/format.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/lib.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/policy.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/src/store.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache/tests/blob_cache_integration.rs +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache-python/Cargo.toml +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache-python/LICENSE +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/sdk-rust/crates/dex-blob-cache-python/README.md +0 -0
- {dex_python_sdk-1.23.0 → dex_python_sdk-1.26.0}/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.
|
|
3
|
+
Version: 1.26.0
|
|
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
|
|
@@ -95,14 +95,17 @@ retain up to four idle credential threads. Sync token lookup must return
|
|
|
95
95
|
promptly. By default, no authorization metadata is sent. Dex uses plaintext
|
|
96
96
|
gRPC, so protect the network path that carries the token.
|
|
97
97
|
|
|
98
|
-
##
|
|
98
|
+
## Workers
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
`
|
|
104
|
-
|
|
105
|
-
SubFlow
|
|
100
|
+
Workers receive tasks through outbound pull streams. `Worker` and `AsyncWorker`
|
|
101
|
+
need only an outbound connection to the Dex Server at `server_address`. Configure
|
|
102
|
+
capacity and shutdown with `WorkerOptions.pull`; its default is
|
|
103
|
+
`PullWorkerOptions()`. Clients and Flows use pull routing automatically.
|
|
104
|
+
|
|
105
|
+
StartFlow and SubFlow always select pull Workers. Updating Flow configuration
|
|
106
|
+
preserves its existing Worker target; an empty `FlowConfig()` changes nothing.
|
|
107
|
+
Before upgrading an application with active push Flows, use an SDK version that
|
|
108
|
+
supports Worker targets to migrate those Flows to pull routing.
|
|
106
109
|
|
|
107
110
|
```python
|
|
108
111
|
import threading
|
|
@@ -118,10 +121,11 @@ worker = Worker(
|
|
|
118
121
|
)
|
|
119
122
|
worker_thread = threading.Thread(target=worker.start)
|
|
120
123
|
worker_thread.start()
|
|
124
|
+
worker.wait_pull_registered(timeout=30)
|
|
121
125
|
client = Client(
|
|
122
126
|
registry,
|
|
123
127
|
cache,
|
|
124
|
-
ClientOptions(server_address="dex.example:8801"
|
|
128
|
+
ClientOptions(server_address="dex.example:8801"),
|
|
125
129
|
)
|
|
126
130
|
try:
|
|
127
131
|
client.start_flow(flow, flow_id, input_value)
|
|
@@ -160,10 +164,7 @@ The generated `app_worker_id` uses the first nonempty `DEX_WORKER_INSTANCE`,
|
|
|
160
164
|
`POD_NAME`, `HOSTNAME`, or system hostname, plus eight random base32 characters.
|
|
161
165
|
An override must uniquely identify one Worker process and change after restart.
|
|
162
166
|
It must contain 1-63 ASCII letters, digits, dots, underscores, or hyphens and
|
|
163
|
-
must not equal a registered Flow type.
|
|
164
|
-
or an advertised address or headless target. Use `WorkerTarget(pull=True)` for
|
|
165
|
-
Client defaults or Flow overrides when the Worker target is not directly in
|
|
166
|
-
scope.
|
|
167
|
+
must not equal a registered Flow type.
|
|
167
168
|
|
|
168
169
|
Pull streams reconnect after failures. A server-directed reconnect waits for
|
|
169
170
|
an active task to finish, then waits up to `stop_drain_timeout` for the server
|
|
@@ -186,7 +187,7 @@ Worker ID queue to register at least once. Timeout raises `TimeoutError`;
|
|
|
186
187
|
async cancellation cancels only that wait. Startup failures reach waiters.
|
|
187
188
|
A permanent rejection before readiness raises `PullRegistrationError`, whose
|
|
188
189
|
`queue` and `error` identify the rejected queue and original transport error.
|
|
189
|
-
|
|
190
|
+
Stopping before readiness raises `RuntimeError`.
|
|
190
191
|
|
|
191
192
|
Use `worker.pull_registration_state()` for subsequent readiness probes. Its
|
|
192
193
|
immutable `queues` expose `queue`, `has_registered_stream`, and
|
|
@@ -240,7 +241,6 @@ to distinguish reserve pressure from full-capacity rejections. The count exclude
|
|
|
240
241
|
full-capacity rejections and unknown names. It counts decline events, including
|
|
241
242
|
repeated declines of the same Step dispatch while Dex retries it. Read its rate
|
|
242
243
|
to assess reserve pressure. It never resets and remains available after shutdown.
|
|
243
|
-
Listening Workers return zero.
|
|
244
244
|
|
|
245
245
|
## Flow state I/O
|
|
246
246
|
|
|
@@ -398,7 +398,7 @@ explicit codec only for a custom encoding or a type Registry cannot derive.
|
|
|
398
398
|
partitions them by definition type.
|
|
399
399
|
|
|
400
400
|
`Worker` and `AsyncWorker` synchronize all registered Indexed Attributes with
|
|
401
|
-
Dex Server before opening
|
|
401
|
+
Dex Server before opening outbound task streams. Existing indexes return immediately;
|
|
402
402
|
failure or the default two-minute deadline aborts startup. An indexed
|
|
403
403
|
`AttributeMap` must provide one fixed `index_key`.
|
|
404
404
|
|
|
@@ -619,9 +619,9 @@ options = dex.StartFlowOptions(
|
|
|
619
619
|
```
|
|
620
620
|
|
|
621
621
|
Register async hooks with `allow_async_handlers=True` and run them with
|
|
622
|
-
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and
|
|
623
|
-
|
|
624
|
-
|
|
622
|
+
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and fails the
|
|
623
|
+
Flow; `CANCEL` cancels it. The deadline is preserved across Flow state
|
|
624
|
+
transfers. A zero or absent timeout
|
|
625
625
|
disables the feature.
|
|
626
626
|
|
|
627
627
|
`Registry` validates every Flow, Step, RPC signature, durable name, lock, and
|
|
@@ -651,12 +651,7 @@ Request IDs are optional for both durable waits. When omitted, the server
|
|
|
651
651
|
derives a stable ID from the Step execution or Attribute condition. Reuse an
|
|
652
652
|
override only for the same wait. `request_timeout` is the total SDK call budget
|
|
653
653
|
across transparent transport reattachments. Zero waits indefinitely.
|
|
654
|
-
|
|
655
|
-
Workflow Execution. A caller timeout or cancellation does not finish an
|
|
656
|
-
accepted durable wait, so an abandoned handler can retain one in-flight slot.
|
|
657
|
-
Set `internal_handler_timeout` only when abandoned waits can approach that
|
|
658
|
-
limit. An active call transparently starts another generation, which counts
|
|
659
|
-
toward the 2,000-Update history limit. Prefer a value comfortably longer than
|
|
654
|
+
A caller timeout or cancellation does not finish an accepted durable wait. Set `internal_handler_timeout` only when abandoned waits can accumulate. An active call transparently registers its wait again. Prefer a value comfortably longer than
|
|
660
655
|
normal request timeouts and reconnect gaps. Zero disables timed rollover.
|
|
661
656
|
Request expiry raises `RequestTimeoutError`.
|
|
662
657
|
|
|
@@ -701,7 +696,7 @@ SubFlow.
|
|
|
701
696
|
Client calls raise concrete `DexServiceError` subclasses. Existing-Flow reads
|
|
702
697
|
(`describe_flow`, `wait_for_flow`, and `time_travel`) raise
|
|
703
698
|
`FlowNotFoundError` when the Flow does not exist. Mutations, RPCs, timer/Step
|
|
704
|
-
waits, config updates, and
|
|
699
|
+
waits, config updates, and state-transfer triggers raise
|
|
705
700
|
`FlowNotActiveOrNotFoundError` when no running Flow can accept the operation.
|
|
706
701
|
|
|
707
702
|
RPCs also use this error when the target Flow cannot be found, including query-only
|
|
@@ -794,8 +789,8 @@ environment:
|
|
|
794
789
|
./run-integration-tests.sh
|
|
795
790
|
```
|
|
796
791
|
|
|
797
|
-
|
|
798
|
-
|
|
792
|
+
The suite uses server-zd and pull Workers. `DEX_INTEG_ENGINE=zd` remains accepted.
|
|
793
|
+
Set `DEX_SERVER_ZD_BINARY` to reuse a built `dex-server-zd`.
|
|
799
794
|
|
|
800
795
|
### Measure integration coverage
|
|
801
796
|
|
|
@@ -868,9 +863,9 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#releases-monorepo-tags) for monorepo ta
|
|
|
868
863
|
## Server protocol compatibility
|
|
869
864
|
|
|
870
865
|
Both `Worker` and `AsyncWorker` call `GetServerInfo`, negotiate the highest
|
|
871
|
-
common protocol, synchronize Attribute indexes, and only then
|
|
872
|
-
|
|
873
|
-
invalid or disjoint intervals, and RPC failures stop startup before
|
|
866
|
+
common protocol, synchronize Attribute indexes, and only then open outbound
|
|
867
|
+
task streams. The initial Python SDK interval is `[1,1]`. Missing information,
|
|
868
|
+
invalid or disjoint intervals, and RPC failures stop startup before polling.
|
|
874
869
|
The current Python SDK interval is `[1,3]`. Protocol 3 adds hard-delete
|
|
875
870
|
Attributes. Workers record the negotiated version at startup and reject each
|
|
876
871
|
handler result that contains a hard-delete Attribute write when it is below 3.
|
|
@@ -888,7 +883,7 @@ original terms as described in [LEGACY_NOTICES.md](LEGACY_NOTICES.md).
|
|
|
888
883
|
|
|
889
884
|
## Search run inclusion
|
|
890
885
|
|
|
891
|
-
|
|
886
|
+
Searches exclude runs with the ContinuedAsNew status by default. server-zd never reports that status. Application queries still
|
|
892
887
|
need `FlowType` when using shared index slots. An explicit inclusion option
|
|
893
888
|
removes only the default exclusion; it does not override query filters. Keep
|
|
894
889
|
the query, inclusion option, and page size consistent across pages.
|
|
@@ -79,14 +79,17 @@ retain up to four idle credential threads. Sync token lookup must return
|
|
|
79
79
|
promptly. By default, no authorization metadata is sent. Dex uses plaintext
|
|
80
80
|
gRPC, so protect the network path that carries the token.
|
|
81
81
|
|
|
82
|
-
##
|
|
82
|
+
## Workers
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
`
|
|
88
|
-
|
|
89
|
-
SubFlow
|
|
84
|
+
Workers receive tasks through outbound pull streams. `Worker` and `AsyncWorker`
|
|
85
|
+
need only an outbound connection to the Dex Server at `server_address`. Configure
|
|
86
|
+
capacity and shutdown with `WorkerOptions.pull`; its default is
|
|
87
|
+
`PullWorkerOptions()`. Clients and Flows use pull routing automatically.
|
|
88
|
+
|
|
89
|
+
StartFlow and SubFlow always select pull Workers. Updating Flow configuration
|
|
90
|
+
preserves its existing Worker target; an empty `FlowConfig()` changes nothing.
|
|
91
|
+
Before upgrading an application with active push Flows, use an SDK version that
|
|
92
|
+
supports Worker targets to migrate those Flows to pull routing.
|
|
90
93
|
|
|
91
94
|
```python
|
|
92
95
|
import threading
|
|
@@ -102,10 +105,11 @@ worker = Worker(
|
|
|
102
105
|
)
|
|
103
106
|
worker_thread = threading.Thread(target=worker.start)
|
|
104
107
|
worker_thread.start()
|
|
108
|
+
worker.wait_pull_registered(timeout=30)
|
|
105
109
|
client = Client(
|
|
106
110
|
registry,
|
|
107
111
|
cache,
|
|
108
|
-
ClientOptions(server_address="dex.example:8801"
|
|
112
|
+
ClientOptions(server_address="dex.example:8801"),
|
|
109
113
|
)
|
|
110
114
|
try:
|
|
111
115
|
client.start_flow(flow, flow_id, input_value)
|
|
@@ -144,10 +148,7 @@ The generated `app_worker_id` uses the first nonempty `DEX_WORKER_INSTANCE`,
|
|
|
144
148
|
`POD_NAME`, `HOSTNAME`, or system hostname, plus eight random base32 characters.
|
|
145
149
|
An override must uniquely identify one Worker process and change after restart.
|
|
146
150
|
It must contain 1-63 ASCII letters, digits, dots, underscores, or hyphens and
|
|
147
|
-
must not equal a registered Flow type.
|
|
148
|
-
or an advertised address or headless target. Use `WorkerTarget(pull=True)` for
|
|
149
|
-
Client defaults or Flow overrides when the Worker target is not directly in
|
|
150
|
-
scope.
|
|
151
|
+
must not equal a registered Flow type.
|
|
151
152
|
|
|
152
153
|
Pull streams reconnect after failures. A server-directed reconnect waits for
|
|
153
154
|
an active task to finish, then waits up to `stop_drain_timeout` for the server
|
|
@@ -170,7 +171,7 @@ Worker ID queue to register at least once. Timeout raises `TimeoutError`;
|
|
|
170
171
|
async cancellation cancels only that wait. Startup failures reach waiters.
|
|
171
172
|
A permanent rejection before readiness raises `PullRegistrationError`, whose
|
|
172
173
|
`queue` and `error` identify the rejected queue and original transport error.
|
|
173
|
-
|
|
174
|
+
Stopping before readiness raises `RuntimeError`.
|
|
174
175
|
|
|
175
176
|
Use `worker.pull_registration_state()` for subsequent readiness probes. Its
|
|
176
177
|
immutable `queues` expose `queue`, `has_registered_stream`, and
|
|
@@ -224,7 +225,6 @@ to distinguish reserve pressure from full-capacity rejections. The count exclude
|
|
|
224
225
|
full-capacity rejections and unknown names. It counts decline events, including
|
|
225
226
|
repeated declines of the same Step dispatch while Dex retries it. Read its rate
|
|
226
227
|
to assess reserve pressure. It never resets and remains available after shutdown.
|
|
227
|
-
Listening Workers return zero.
|
|
228
228
|
|
|
229
229
|
## Flow state I/O
|
|
230
230
|
|
|
@@ -382,7 +382,7 @@ explicit codec only for a custom encoding or a type Registry cannot derive.
|
|
|
382
382
|
partitions them by definition type.
|
|
383
383
|
|
|
384
384
|
`Worker` and `AsyncWorker` synchronize all registered Indexed Attributes with
|
|
385
|
-
Dex Server before opening
|
|
385
|
+
Dex Server before opening outbound task streams. Existing indexes return immediately;
|
|
386
386
|
failure or the default two-minute deadline aborts startup. An indexed
|
|
387
387
|
`AttributeMap` must provide one fixed `index_key`.
|
|
388
388
|
|
|
@@ -603,9 +603,9 @@ options = dex.StartFlowOptions(
|
|
|
603
603
|
```
|
|
604
604
|
|
|
605
605
|
Register async hooks with `allow_async_handlers=True` and run them with
|
|
606
|
-
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and
|
|
607
|
-
|
|
608
|
-
|
|
606
|
+
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and fails the
|
|
607
|
+
Flow; `CANCEL` cancels it. The deadline is preserved across Flow state
|
|
608
|
+
transfers. A zero or absent timeout
|
|
609
609
|
disables the feature.
|
|
610
610
|
|
|
611
611
|
`Registry` validates every Flow, Step, RPC signature, durable name, lock, and
|
|
@@ -635,12 +635,7 @@ Request IDs are optional for both durable waits. When omitted, the server
|
|
|
635
635
|
derives a stable ID from the Step execution or Attribute condition. Reuse an
|
|
636
636
|
override only for the same wait. `request_timeout` is the total SDK call budget
|
|
637
637
|
across transparent transport reattachments. Zero waits indefinitely.
|
|
638
|
-
|
|
639
|
-
Workflow Execution. A caller timeout or cancellation does not finish an
|
|
640
|
-
accepted durable wait, so an abandoned handler can retain one in-flight slot.
|
|
641
|
-
Set `internal_handler_timeout` only when abandoned waits can approach that
|
|
642
|
-
limit. An active call transparently starts another generation, which counts
|
|
643
|
-
toward the 2,000-Update history limit. Prefer a value comfortably longer than
|
|
638
|
+
A caller timeout or cancellation does not finish an accepted durable wait. Set `internal_handler_timeout` only when abandoned waits can accumulate. An active call transparently registers its wait again. Prefer a value comfortably longer than
|
|
644
639
|
normal request timeouts and reconnect gaps. Zero disables timed rollover.
|
|
645
640
|
Request expiry raises `RequestTimeoutError`.
|
|
646
641
|
|
|
@@ -685,7 +680,7 @@ SubFlow.
|
|
|
685
680
|
Client calls raise concrete `DexServiceError` subclasses. Existing-Flow reads
|
|
686
681
|
(`describe_flow`, `wait_for_flow`, and `time_travel`) raise
|
|
687
682
|
`FlowNotFoundError` when the Flow does not exist. Mutations, RPCs, timer/Step
|
|
688
|
-
waits, config updates, and
|
|
683
|
+
waits, config updates, and state-transfer triggers raise
|
|
689
684
|
`FlowNotActiveOrNotFoundError` when no running Flow can accept the operation.
|
|
690
685
|
|
|
691
686
|
RPCs also use this error when the target Flow cannot be found, including query-only
|
|
@@ -778,8 +773,8 @@ environment:
|
|
|
778
773
|
./run-integration-tests.sh
|
|
779
774
|
```
|
|
780
775
|
|
|
781
|
-
|
|
782
|
-
|
|
776
|
+
The suite uses server-zd and pull Workers. `DEX_INTEG_ENGINE=zd` remains accepted.
|
|
777
|
+
Set `DEX_SERVER_ZD_BINARY` to reuse a built `dex-server-zd`.
|
|
783
778
|
|
|
784
779
|
### Measure integration coverage
|
|
785
780
|
|
|
@@ -852,9 +847,9 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#releases-monorepo-tags) for monorepo ta
|
|
|
852
847
|
## Server protocol compatibility
|
|
853
848
|
|
|
854
849
|
Both `Worker` and `AsyncWorker` call `GetServerInfo`, negotiate the highest
|
|
855
|
-
common protocol, synchronize Attribute indexes, and only then
|
|
856
|
-
|
|
857
|
-
invalid or disjoint intervals, and RPC failures stop startup before
|
|
850
|
+
common protocol, synchronize Attribute indexes, and only then open outbound
|
|
851
|
+
task streams. The initial Python SDK interval is `[1,1]`. Missing information,
|
|
852
|
+
invalid or disjoint intervals, and RPC failures stop startup before polling.
|
|
858
853
|
The current Python SDK interval is `[1,3]`. Protocol 3 adds hard-delete
|
|
859
854
|
Attributes. Workers record the negotiated version at startup and reject each
|
|
860
855
|
handler result that contains a hard-delete Attribute write when it is below 3.
|
|
@@ -872,7 +867,7 @@ original terms as described in [LEGACY_NOTICES.md](LEGACY_NOTICES.md).
|
|
|
872
867
|
|
|
873
868
|
## Search run inclusion
|
|
874
869
|
|
|
875
|
-
|
|
870
|
+
Searches exclude runs with the ContinuedAsNew status by default. server-zd never reports that status. Application queries still
|
|
876
871
|
need `FlowType` when using shared index slots. An explicit inclusion option
|
|
877
872
|
removes only the default exclusion; it does not override query filters. Keep
|
|
878
873
|
the query, inclusion option, and page size consistent across pages.
|
|
@@ -124,7 +124,7 @@ from dex.timer import Timer
|
|
|
124
124
|
from dex.wait import Wait
|
|
125
125
|
from dex.wait_options import WaitForAttributeOptions, WaitForStepCompletionOptions
|
|
126
126
|
from dex.worker import Worker
|
|
127
|
-
from dex.worker_options import PullWorkerOptions, WorkerOptions
|
|
127
|
+
from dex.worker_options import PullWorkerOptions, WorkerOptions
|
|
128
128
|
|
|
129
129
|
__all__ = [
|
|
130
130
|
"BOOL",
|
|
@@ -226,7 +226,6 @@ __all__ = [
|
|
|
226
226
|
"Worker",
|
|
227
227
|
"WorkerInvocationError",
|
|
228
228
|
"WorkerOptions",
|
|
229
|
-
"WorkerTarget",
|
|
230
229
|
"PullWorkerOptions",
|
|
231
230
|
"PullRegistrationError",
|
|
232
231
|
"PullRegistrationState",
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import traceback
|
|
12
12
|
from dataclasses import dataclass
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import Literal, cast
|
|
14
14
|
|
|
15
15
|
import grpc
|
|
16
16
|
from google.protobuf import any_pb2
|
|
@@ -165,23 +165,6 @@ def _worker_code(details: pb.ServiceErrorResponse | None) -> grpc.StatusCode | N
|
|
|
165
165
|
)
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
def abort_worker_error(
|
|
169
|
-
context: grpc.ServicerContext,
|
|
170
|
-
error: BaseException,
|
|
171
|
-
) -> None:
|
|
172
|
-
context.abort_with_status(rpc_status.to_status(_worker_error_status(error)))
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
async def async_abort_worker_error(
|
|
176
|
-
context: grpc.aio.ServicerContext[Any, Any],
|
|
177
|
-
error: BaseException,
|
|
178
|
-
) -> None:
|
|
179
|
-
# types-grpcio on 3.11 omits aio abort_with_status; runtime provides it.
|
|
180
|
-
await cast(Any, context).abort_with_status(
|
|
181
|
-
rpc_status.to_status(_worker_error_status(error))
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
|
|
185
168
|
def _worker_error_status(error: BaseException) -> status_pb2.Status:
|
|
186
169
|
retry_after_error: RetryAfterError | None = None
|
|
187
170
|
reported = error
|
|
@@ -805,6 +805,21 @@ class PullStream:
|
|
|
805
805
|
async with self._send_lock:
|
|
806
806
|
if request.HasField("task_frame"):
|
|
807
807
|
frame = request.task_frame
|
|
808
|
+
is_progress_frame = (
|
|
809
|
+
frame.HasField("wait_for")
|
|
810
|
+
and frame.wait_for.WhichOneof("output")
|
|
811
|
+
in ("heartbeat", "stream_write")
|
|
812
|
+
or frame.HasField("execute")
|
|
813
|
+
and frame.execute.WhichOneof("output")
|
|
814
|
+
in ("heartbeat", "stream_write")
|
|
815
|
+
)
|
|
816
|
+
if (
|
|
817
|
+
frame.task_id != self.task_id
|
|
818
|
+
or self._is_final_frame_sent
|
|
819
|
+
or not self._active.is_set()
|
|
820
|
+
and is_progress_frame
|
|
821
|
+
):
|
|
822
|
+
return
|
|
808
823
|
if (
|
|
809
824
|
frame.HasField("rpc")
|
|
810
825
|
or frame.HasField("worker_error")
|
|
@@ -711,6 +711,9 @@ class WorkerDispatcher:
|
|
|
711
711
|
mapped.flow_config_override.CopyFrom(
|
|
712
712
|
self._map_sub_flow_config(options.config_override)
|
|
713
713
|
)
|
|
714
|
+
mapped.flow_config_override.worker_target.CopyFrom(
|
|
715
|
+
pb.WorkerTarget(is_pull_mode=True)
|
|
716
|
+
)
|
|
714
717
|
return mapped
|
|
715
718
|
|
|
716
719
|
def _result_attribute_writes(
|
|
@@ -761,14 +764,7 @@ class WorkerDispatcher:
|
|
|
761
764
|
StepDurability.SYNC: pb.STEP_DURABILITY_SYNC,
|
|
762
765
|
StepDurability.ASYNC: pb.STEP_DURABILITY_ASYNC,
|
|
763
766
|
}[config.step_durability]
|
|
764
|
-
|
|
765
|
-
mapped.worker_target.CopyFrom(
|
|
766
|
-
pb.WorkerTarget(
|
|
767
|
-
address=config.worker_target.address,
|
|
768
|
-
is_headless_address=config.worker_target.headless,
|
|
769
|
-
is_pull_mode=config.worker_target.pull,
|
|
770
|
-
)
|
|
771
|
-
)
|
|
767
|
+
mapped.worker_target.CopyFrom(pb.WorkerTarget(is_pull_mode=True))
|
|
772
768
|
if config.attribute_store_names is not None:
|
|
773
769
|
mapped.attribute_store_names.CopyFrom(
|
|
774
770
|
pb.AttributeStoreNames(names=config.attribute_store_names)
|
|
@@ -107,7 +107,7 @@ class AsyncClient:
|
|
|
107
107
|
Args:
|
|
108
108
|
registry: The Flow Registry used for validation and codecs.
|
|
109
109
|
blob_cache: An open cache used for asynchronous hydration.
|
|
110
|
-
options: Service address
|
|
110
|
+
options: Service address and bearer credential;
|
|
111
111
|
``None`` uses defaults and sends no authorization metadata.
|
|
112
112
|
"""
|
|
113
113
|
self.registry = registry
|
|
@@ -1038,7 +1038,11 @@ class AsyncClient:
|
|
|
1038
1038
|
raise
|
|
1039
1039
|
|
|
1040
1040
|
async def update_flow_config(self, flow_id: str, config: FlowConfig) -> None:
|
|
1041
|
-
"""
|
|
1041
|
+
"""Update specified mutable configuration fields for an active Flow.
|
|
1042
|
+
|
|
1043
|
+
The update affects later decisions and does not recall work already
|
|
1044
|
+
dispatched. Unspecified fields and the existing Worker target remain
|
|
1045
|
+
unchanged. An empty ``FlowConfig()`` leaves all configuration unchanged.
|
|
1042
1046
|
|
|
1043
1047
|
Args:
|
|
1044
1048
|
flow_id: The non-empty active Flow ID.
|
|
@@ -1193,13 +1197,12 @@ class AsyncClient:
|
|
|
1193
1197
|
_apply_attribute_store_sync(write, definition)
|
|
1194
1198
|
_apply_hard_delete_on_null(write, definition)
|
|
1195
1199
|
mapped.attributes.append(write)
|
|
1196
|
-
|
|
1197
|
-
options.config_override
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
)
|
|
1200
|
+
mapped.flow_config_override.CopyFrom(
|
|
1201
|
+
self._map_flow_config(options.config_override)
|
|
1202
|
+
)
|
|
1203
|
+
mapped.flow_config_override.worker_target.CopyFrom(
|
|
1204
|
+
pb.WorkerTarget(is_pull_mode=True)
|
|
1205
|
+
)
|
|
1203
1206
|
return mapped
|
|
1204
1207
|
|
|
1205
1208
|
def _map_flow_config(self, config: FlowConfig | None) -> pb.FlowConfig:
|
|
@@ -1236,19 +1239,6 @@ class AsyncClient:
|
|
|
1236
1239
|
mapped.attribute_store_names.CopyFrom(
|
|
1237
1240
|
pb.AttributeStoreNames(names=config.attribute_store_names)
|
|
1238
1241
|
)
|
|
1239
|
-
target = (
|
|
1240
|
-
config.worker_target
|
|
1241
|
-
if config is not None and config.worker_target is not None
|
|
1242
|
-
else self.options.worker_target
|
|
1243
|
-
)
|
|
1244
|
-
if target is not None:
|
|
1245
|
-
mapped.worker_target.CopyFrom(
|
|
1246
|
-
pb.WorkerTarget(
|
|
1247
|
-
address=target.address,
|
|
1248
|
-
is_headless_address=target.headless,
|
|
1249
|
-
is_pull_mode=target.pull,
|
|
1250
|
-
)
|
|
1251
|
-
)
|
|
1252
1242
|
return mapped
|
|
1253
1243
|
|
|
1254
1244
|
@staticmethod
|