dex-python-sdk 1.14.0__tar.gz → 1.14.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.
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/PKG-INFO +8 -6
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/README.md +7 -5
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_pull_worker.py +46 -17
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/pyproject.toml +1 -1
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/LEGACY_NOTICES.md +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/LICENSE +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/__init__.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_async_value_hydrator.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_async_worker_dispatcher.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_async_worker_service.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_credential_transport.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_grpc_errors.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_invocation_context.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_native.pyi +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_server_protocol.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_utils.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_value_hydrator.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_value_mapper.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_worker_dispatcher.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/_worker_service.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/async_client.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/async_worker.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/attribute.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/attribute_match.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/blob_cache.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/channel.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/client.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/client_options.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/codec.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/condition.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/context.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/credential.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/dexpb/__init__.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/dexpb/dex_pb2.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/dexpb/dex_pb2.pyi +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/dexpb/dex_pb2_grpc.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/flow.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/flow_config.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/flow_info.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/flow_options.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/flow_result.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/pull_registration.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/py.typed +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/rpc_invoke_options.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/runtime_errors.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/step.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/step_execution.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/stream.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/subflow.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/timer.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/wait.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/wait_options.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/worker.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/dex/worker_options.py +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/Cargo.lock +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/Cargo.toml +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/Cargo.toml +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/LICENSE +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/config.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/entry.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/error.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/format.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/lib.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/policy.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/store.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/tests/blob_cache_integration.rs +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache-python/Cargo.toml +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache-python/LICENSE +0 -0
- {dex_python_sdk-1.14.0 → dex_python_sdk-1.14.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.14.
|
|
3
|
+
Version: 1.14.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
|
|
@@ -94,11 +94,13 @@ The Worker polls its sticky queue and every registered Flow type queue. Flow
|
|
|
94
94
|
type names must be unique within a Dex server. `max_concurrent_tasks` defaults
|
|
95
95
|
to the CPU count, and `idle_streams_per_queue` defaults to one. At capacity,
|
|
96
96
|
the Worker rejects an assignment so Dex can reassign it. Each stream runs one
|
|
97
|
-
task at a time; Step heartbeat and stream writes use the same stream.
|
|
98
|
-
|
|
99
|
-
max_concurrent_tasks
|
|
100
|
-
streams
|
|
101
|
-
|
|
97
|
+
task at a time; Step heartbeat and stream writes use the same stream. After tasks finish, the Worker
|
|
98
|
+
gracefully closes surplus idle streams while preserving readiness. After load drops,
|
|
99
|
+
the steady-state bound is `max_concurrent_tasks + (1 + number of Flow types) *
|
|
100
|
+
idle_streams_per_queue` streams. The transient peak during a burst remains bounded
|
|
101
|
+
by the matching caps. Size these options for `matching.maxConcurrentTasksCap` per
|
|
102
|
+
app Worker ID per matching owner (256 by default) and `matching.maxStreams` per
|
|
103
|
+
Matching instance (100,000 by default).
|
|
102
104
|
|
|
103
105
|
The Worker rejects an unregistered Step or RPC by name. Dex retries that task
|
|
104
106
|
on another pull Worker without consuming a Step attempt, including when the
|
|
@@ -78,11 +78,13 @@ The Worker polls its sticky queue and every registered Flow type queue. Flow
|
|
|
78
78
|
type names must be unique within a Dex server. `max_concurrent_tasks` defaults
|
|
79
79
|
to the CPU count, and `idle_streams_per_queue` defaults to one. At capacity,
|
|
80
80
|
the Worker rejects an assignment so Dex can reassign it. Each stream runs one
|
|
81
|
-
task at a time; Step heartbeat and stream writes use the same stream.
|
|
82
|
-
|
|
83
|
-
max_concurrent_tasks
|
|
84
|
-
streams
|
|
85
|
-
|
|
81
|
+
task at a time; Step heartbeat and stream writes use the same stream. After tasks finish, the Worker
|
|
82
|
+
gracefully closes surplus idle streams while preserving readiness. After load drops,
|
|
83
|
+
the steady-state bound is `max_concurrent_tasks + (1 + number of Flow types) *
|
|
84
|
+
idle_streams_per_queue` streams. The transient peak during a burst remains bounded
|
|
85
|
+
by the matching caps. Size these options for `matching.maxConcurrentTasksCap` per
|
|
86
|
+
app Worker ID per matching owner (256 by default) and `matching.maxStreams` per
|
|
87
|
+
Matching instance (100,000 by default).
|
|
86
88
|
|
|
87
89
|
The Worker rejects an unregistered Step or RPC by name. Dex retries that task
|
|
88
90
|
on another pull Worker without consuming a Step attempt, including when the
|
|
@@ -170,6 +170,8 @@ class PullWorkerRuntime:
|
|
|
170
170
|
def _reconcile(self, stub: Any) -> None:
|
|
171
171
|
if self._stopping is None or self._stopping.is_set():
|
|
172
172
|
return
|
|
173
|
+
for stream in tuple(self._streams):
|
|
174
|
+
stream.try_retire()
|
|
173
175
|
for queue in self.queues:
|
|
174
176
|
idle = sum(
|
|
175
177
|
stream.queue == queue
|
|
@@ -279,6 +281,8 @@ class PullStream:
|
|
|
279
281
|
self.is_busy = False
|
|
280
282
|
self._is_registered = False
|
|
281
283
|
self.is_draining = False
|
|
284
|
+
self._is_retiring = False
|
|
285
|
+
self._retirement_requested = asyncio.Event()
|
|
282
286
|
self.is_half_closing = False
|
|
283
287
|
self._active = threading.Event()
|
|
284
288
|
self._call: Any = None
|
|
@@ -321,7 +325,11 @@ class PullStream:
|
|
|
321
325
|
self.runtime._rejection_stop_task = asyncio.create_task(
|
|
322
326
|
self.runtime.stop()
|
|
323
327
|
)
|
|
324
|
-
if
|
|
328
|
+
if (
|
|
329
|
+
self.runtime.is_stopping
|
|
330
|
+
or self.runtime._permanent_error is not None
|
|
331
|
+
or self._is_retiring
|
|
332
|
+
):
|
|
325
333
|
break
|
|
326
334
|
if self._is_reconnecting:
|
|
327
335
|
self._is_reconnecting = False
|
|
@@ -378,11 +386,12 @@ class PullStream:
|
|
|
378
386
|
)
|
|
379
387
|
was_registered = False
|
|
380
388
|
reader: asyncio.Task[Any] | None = None
|
|
389
|
+
retirement = asyncio.create_task(self._retirement_requested.wait())
|
|
381
390
|
try:
|
|
382
391
|
while not self.runtime.is_stopping or self.is_busy:
|
|
383
392
|
if reader is None:
|
|
384
393
|
reader = asyncio.create_task(self._call.read())
|
|
385
|
-
waiting: set[asyncio.Task[Any]] = {reader}
|
|
394
|
+
waiting: set[asyncio.Task[Any]] = {reader, retirement}
|
|
386
395
|
if self.handler_task is not None:
|
|
387
396
|
waiting.add(self.handler_task)
|
|
388
397
|
completed, _ = await asyncio.wait(
|
|
@@ -390,22 +399,23 @@ class PullStream:
|
|
|
390
399
|
)
|
|
391
400
|
if self.handler_task in completed:
|
|
392
401
|
await self._finish_handler()
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (
|
|
398
|
-
frame is not _GRPC_AIO_EOF
|
|
399
|
-
and frame.WhichOneof("frame") == "task"
|
|
400
|
-
):
|
|
401
|
-
await self._reject_task(frame.task)
|
|
402
|
-
self.is_half_closing = True
|
|
403
|
-
self.runtime.signal()
|
|
404
|
-
await self._call.done_writing()
|
|
405
|
-
await self._await_stream_eof(reader)
|
|
402
|
+
self.try_retire()
|
|
403
|
+
if self.is_draining and not self.is_busy:
|
|
404
|
+
if reader.done():
|
|
405
|
+
frame = reader.result()
|
|
406
406
|
reader = None
|
|
407
|
-
|
|
408
|
-
|
|
407
|
+
if (
|
|
408
|
+
frame is not _GRPC_AIO_EOF
|
|
409
|
+
and frame.WhichOneof("frame") == "task"
|
|
410
|
+
):
|
|
411
|
+
await self._reject_task(frame.task)
|
|
412
|
+
self.is_half_closing = True
|
|
413
|
+
self.runtime.signal()
|
|
414
|
+
await self._call.done_writing()
|
|
415
|
+
await self._await_stream_eof(reader)
|
|
416
|
+
reader = None
|
|
417
|
+
self._is_reconnecting = not self._is_retiring
|
|
418
|
+
return was_registered
|
|
409
419
|
if reader not in completed:
|
|
410
420
|
continue
|
|
411
421
|
frame = reader.result()
|
|
@@ -425,6 +435,7 @@ class PullStream:
|
|
|
425
435
|
was_registered = True
|
|
426
436
|
self._is_registered = True
|
|
427
437
|
self.runtime.registration.record_registered_stream(self.queue)
|
|
438
|
+
self.runtime.signal()
|
|
428
439
|
continue
|
|
429
440
|
if kind == "task":
|
|
430
441
|
await self._start_task(frame.task)
|
|
@@ -442,6 +453,8 @@ class PullStream:
|
|
|
442
453
|
self._is_reconnecting = True
|
|
443
454
|
return was_registered
|
|
444
455
|
finally:
|
|
456
|
+
retirement.cancel()
|
|
457
|
+
await asyncio.gather(retirement, return_exceptions=True)
|
|
445
458
|
self.is_half_closing = False
|
|
446
459
|
self.cancel_handler()
|
|
447
460
|
if self.handler_task is not None:
|
|
@@ -658,6 +671,22 @@ class PullStream:
|
|
|
658
671
|
self._active.clear()
|
|
659
672
|
self.runtime.finish_task()
|
|
660
673
|
|
|
674
|
+
def try_retire(self) -> None:
|
|
675
|
+
if self.is_busy or self.is_draining or not self._is_registered:
|
|
676
|
+
return
|
|
677
|
+
idle_replacements = sum(
|
|
678
|
+
candidate is not self
|
|
679
|
+
and candidate.queue == self.queue
|
|
680
|
+
and candidate._is_registered
|
|
681
|
+
and not candidate.is_busy
|
|
682
|
+
and not candidate.is_draining
|
|
683
|
+
for candidate in self.runtime._streams
|
|
684
|
+
)
|
|
685
|
+
if idle_replacements >= self.runtime.idle_streams_per_queue:
|
|
686
|
+
self.is_draining = True
|
|
687
|
+
self._is_retiring = True
|
|
688
|
+
self._retirement_requested.set()
|
|
689
|
+
|
|
661
690
|
def cancel_handler(self) -> None:
|
|
662
691
|
self._active.clear()
|
|
663
692
|
if self.runtime._executor is None and self.handler_task is not None:
|
|
@@ -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.14.
|
|
4
|
+
version = "1.14.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/config.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/format.rs
RENAMED
|
File without changes
|
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache/src/policy.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache-python/Cargo.toml
RENAMED
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache-python/LICENSE
RENAMED
|
File without changes
|
{dex_python_sdk-1.14.0 → dex_python_sdk-1.14.1}/sdk-rust/crates/dex-blob-cache-python/src/lib.rs
RENAMED
|
File without changes
|