durable-workflow 2.5.6__tar.gz → 2.5.8__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.
- {durable_workflow-2.5.6/src/durable_workflow.egg-info → durable_workflow-2.5.8}/PKG-INFO +11 -9
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/README.md +10 -8
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/pyproject.toml +4 -4
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/client.py +2 -1
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/worker.py +21 -3
- {durable_workflow-2.5.6 → durable_workflow-2.5.8/src/durable_workflow.egg-info}/PKG-INFO +11 -9
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_opening.py +2 -2
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_client.py +6 -1
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_cancellation_client.py +4 -7
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_cancellation_worker.py +1 -1
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_remote_worker.py +3 -3
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_client.py +2 -2
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_release_metadata.py +2 -2
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_worker.py +64 -1
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/LICENSE +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/setup.cfg +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/__init__.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_activity_process.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_avro.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_cancellation_scope.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_cancellation_scope_history.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_cooperative_cancellation.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_prepared_local_activity.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_sticky_workflow_cache.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/activity.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/auth_composition.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/cancellation.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/errors.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/external_storage.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/external_task_input.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/external_task_result.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/history_bundle_verify.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/interceptors.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/invocable.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/metrics.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/nexus.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/py.typed +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/python_conformance.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/replay_conformance.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/replay_verify.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/retry_policy.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/serializer.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/sync.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/testing.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/worker_session.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/workflow.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/workflow_updates_conformance.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/SOURCES.txt +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/dependency_links.txt +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/entry_points.txt +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/requires.txt +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/top_level.txt +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_activity_cancellation_policies.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_activity_context.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_activity_process.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_auth_composition.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_avro_value_benchmark.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_avro_value_protocol.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_context.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_remaining_time.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_admission.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_authoring.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_boundary.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_child_workflow_policies.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_ci_checkout.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_ci_integration_endpoint.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_client_timeouts.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_codec_regression_corpus.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_descendants.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_groups.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_history.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_condition_replay_drift.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_control_plane_parity_fixtures.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_cancellation.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_docstring_cross_references.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_durable_selection.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_errors.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_external_storage.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_external_task_input.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_external_task_result.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_golden_history_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_history_bundle_verify.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_history_event_contract.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_invocable.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_message_streams.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_metrics.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_nexus_namespace.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_nexus_wire.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_order_processing_example.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_parallel_completion_order_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_parallel_saga_authoring.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_patch_history.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_pending_operation_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_groups.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_policies.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_worker.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_public_boundary_scanner.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_pypi_project_surface.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_python_conformance.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_queries.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_readme_quickstart.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_redrive_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_registration_ambiguity.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_replay_conformance.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_replay_regression_corpus.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_replay_verify.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_retry_policy.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_run_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_runtime_external_payload_transport.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_schedules.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_scoped_run_cancellation_context.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_serializer.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_signals.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_sleep.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_standalone_activity_client.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_sticky_execution.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_storage_admission.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_sync.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_testing_harness.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_update_signal_condition_replay.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_updates.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_wait_condition.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_worker_session.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_entrypoint_validation.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_result_timeout.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_streams.py +0 -0
- {durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_updates_conformance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: durable-workflow
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.8
|
|
4
4
|
Summary: Python client and worker SDK for Durable Workflow Cloud and self-hosted Server
|
|
5
5
|
Author: Durable Workflow Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -155,12 +155,15 @@ capabilities with Server at startup. Use stable `2.x` SDK and Server channels
|
|
|
155
155
|
for new applications. The [compatibility guide](https://durable-workflow.com/docs/2.0/compatibility/)
|
|
156
156
|
documents protocol and upgrade guarantees.
|
|
157
157
|
|
|
158
|
-
##
|
|
158
|
+
## Worker protocol and cooperative cancellation
|
|
159
|
+
|
|
160
|
+
Workers use protocol 1.20 by default. For a Server that supports only 1.19, set
|
|
161
|
+
`DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION=1.19`. This changes the request protocol
|
|
162
|
+
without enabling optional worker features.
|
|
159
163
|
|
|
160
164
|
Use `request_cancellation()` for bounded, replayable workflow cleanup. Opt in
|
|
161
165
|
against a Server that advertises protocol 1.20 and the required capabilities:
|
|
162
|
-
|
|
163
|
-
`cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
166
|
+
include `cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
164
167
|
admission also needs `prepared_local_activities`, with
|
|
165
168
|
`prepared_local_activity_cancellation_policies` for explicit local policies.
|
|
166
169
|
Independently cancellable scopes remain disabled.
|
|
@@ -196,11 +199,10 @@ to true. CI verifies that checkout, builds the candidate Server, enables protoco
|
|
|
196
199
|
authority and exact source provenance. An optional exact `native_commit` mounts
|
|
197
200
|
that public Native checkout read-only into the test stack. The image's published
|
|
198
201
|
Composer authority stays intact and the evidence identifies the source overlay.
|
|
199
|
-
These are source qualification runs. For a local
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
keeps protocol 1.19 and skips this unpublished feature's connected cases.
|
|
202
|
+
These are source qualification runs. For a local candidate, set
|
|
203
|
+
`DURABLE_WORKFLOW_COOPERATIVE_QUALIFICATION=1` for pytest. These cases fail if the
|
|
204
|
+
runtime does not discover the required capability. Ordinary CI uses the SDK's
|
|
205
|
+
default protocol and skips the optional connected cooperative cases.
|
|
204
206
|
|
|
205
207
|
## License
|
|
206
208
|
|
|
@@ -115,12 +115,15 @@ capabilities with Server at startup. Use stable `2.x` SDK and Server channels
|
|
|
115
115
|
for new applications. The [compatibility guide](https://durable-workflow.com/docs/2.0/compatibility/)
|
|
116
116
|
documents protocol and upgrade guarantees.
|
|
117
117
|
|
|
118
|
-
##
|
|
118
|
+
## Worker protocol and cooperative cancellation
|
|
119
|
+
|
|
120
|
+
Workers use protocol 1.20 by default. For a Server that supports only 1.19, set
|
|
121
|
+
`DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION=1.19`. This changes the request protocol
|
|
122
|
+
without enabling optional worker features.
|
|
119
123
|
|
|
120
124
|
Use `request_cancellation()` for bounded, replayable workflow cleanup. Opt in
|
|
121
125
|
against a Server that advertises protocol 1.20 and the required capabilities:
|
|
122
|
-
|
|
123
|
-
`cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
126
|
+
include `cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
124
127
|
admission also needs `prepared_local_activities`, with
|
|
125
128
|
`prepared_local_activity_cancellation_policies` for explicit local policies.
|
|
126
129
|
Independently cancellable scopes remain disabled.
|
|
@@ -156,11 +159,10 @@ to true. CI verifies that checkout, builds the candidate Server, enables protoco
|
|
|
156
159
|
authority and exact source provenance. An optional exact `native_commit` mounts
|
|
157
160
|
that public Native checkout read-only into the test stack. The image's published
|
|
158
161
|
Composer authority stays intact and the evidence identifies the source overlay.
|
|
159
|
-
These are source qualification runs. For a local
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
keeps protocol 1.19 and skips this unpublished feature's connected cases.
|
|
162
|
+
These are source qualification runs. For a local candidate, set
|
|
163
|
+
`DURABLE_WORKFLOW_COOPERATIVE_QUALIFICATION=1` for pytest. These cases fail if the
|
|
164
|
+
runtime does not discover the required capability. Ordinary CI uses the SDK's
|
|
165
|
+
default protocol and skips the optional connected cooperative cases.
|
|
164
166
|
|
|
165
167
|
## License
|
|
166
168
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "durable-workflow"
|
|
7
|
-
version = "2.5.
|
|
7
|
+
version = "2.5.8"
|
|
8
8
|
description = "Python client and worker SDK for Durable Workflow Cloud and self-hosted Server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -71,10 +71,10 @@ durable-workflow-replay-conformance = "durable_workflow.replay_conformance:main"
|
|
|
71
71
|
durable-workflow-workflow-updates-conformance = "durable_workflow.workflow_updates_conformance:main"
|
|
72
72
|
|
|
73
73
|
[tool.durable-workflow]
|
|
74
|
-
product-train = "2.5.
|
|
75
|
-
registry-version = "2.5.
|
|
74
|
+
product-train = "2.5.8"
|
|
75
|
+
registry-version = "2.5.8"
|
|
76
76
|
supported-server-versions = "2.5.16"
|
|
77
|
-
worker-protocol-version = "1.
|
|
77
|
+
worker-protocol-version = "1.20"
|
|
78
78
|
control-plane-version = "2"
|
|
79
79
|
durable-selection = true
|
|
80
80
|
durable-selection-minimum-worker-protocol-version = "1.19"
|
|
@@ -72,7 +72,8 @@ from .nexus import NexusOperationResult, nexus_request_payload
|
|
|
72
72
|
from .retry_policy import TransportRetryPolicy
|
|
73
73
|
from .worker_session import WorkerSessionOptions
|
|
74
74
|
|
|
75
|
-
PROTOCOL_VERSION = "1.
|
|
75
|
+
PROTOCOL_VERSION = "1.20"
|
|
76
|
+
MINIMUM_WORKER_PROTOCOL_VERSION = "1.19"
|
|
76
77
|
CONTROL_PLANE_VERSION = "2"
|
|
77
78
|
PORTABLE_WORKER_AFFINITY_CAPABILITY_MANIFEST: dict[str, dict[str, str | bool]] = {
|
|
78
79
|
"local_activities": {
|
|
@@ -55,6 +55,7 @@ from .client import (
|
|
|
55
55
|
CONTROL_PLANE_REQUEST_CONTRACT_VERSION,
|
|
56
56
|
CONTROL_PLANE_VERSION,
|
|
57
57
|
DEFAULT_SDK_VERSION,
|
|
58
|
+
MINIMUM_WORKER_PROTOCOL_VERSION,
|
|
58
59
|
PORTABLE_WORKER_AFFINITY_CAPABILITY_MANIFEST,
|
|
59
60
|
PROTOCOL_VERSION,
|
|
60
61
|
Client,
|
|
@@ -877,6 +878,16 @@ def _server_protocol_compatible(server_version: str, sdk_version: str) -> bool:
|
|
|
877
878
|
|
|
878
879
|
|
|
879
880
|
def _validate_server_compatibility(info: dict[str, Any]) -> None:
|
|
881
|
+
requested_protocol = _protocol_version_from_env(
|
|
882
|
+
"DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", PROTOCOL_VERSION,
|
|
883
|
+
)
|
|
884
|
+
if requested_protocol not in (MINIMUM_WORKER_PROTOCOL_VERSION, PROTOCOL_VERSION):
|
|
885
|
+
raise RuntimeError(
|
|
886
|
+
"Server compatibility error: sdk-python supports worker protocol "
|
|
887
|
+
f"{MINIMUM_WORKER_PROTOCOL_VERSION} or protocol {PROTOCOL_VERSION}; "
|
|
888
|
+
f"requested {requested_protocol!r}."
|
|
889
|
+
)
|
|
890
|
+
|
|
880
891
|
control_plane = info.get("control_plane")
|
|
881
892
|
if not isinstance(control_plane, dict):
|
|
882
893
|
raise RuntimeError(
|
|
@@ -914,15 +925,15 @@ def _validate_server_compatibility(info: dict[str, Any]) -> None:
|
|
|
914
925
|
if not isinstance(worker_protocol, dict):
|
|
915
926
|
raise RuntimeError(
|
|
916
927
|
"Server compatibility error: missing worker_protocol manifest; "
|
|
917
|
-
f"sdk-python requires worker_protocol.version {
|
|
928
|
+
f"sdk-python requires worker_protocol.version {requested_protocol}."
|
|
918
929
|
)
|
|
919
930
|
|
|
920
931
|
worker_protocol_version = _manifest_version(worker_protocol)
|
|
921
|
-
if not _server_protocol_compatible(worker_protocol_version,
|
|
932
|
+
if not _server_protocol_compatible(worker_protocol_version, requested_protocol):
|
|
922
933
|
raise RuntimeError(
|
|
923
934
|
"Server compatibility error: incompatible worker_protocol.version "
|
|
924
935
|
f"{worker_protocol_version!r}; sdk-python requires major-equal and "
|
|
925
|
-
f"minor>={
|
|
936
|
+
f"minor>={requested_protocol!r}."
|
|
926
937
|
)
|
|
927
938
|
|
|
928
939
|
auth_composition = info.get("auth_composition_contract")
|
|
@@ -4233,6 +4244,7 @@ class Worker:
|
|
|
4233
4244
|
"""
|
|
4234
4245
|
background_tasks: list[asyncio.Task[Any]] = []
|
|
4235
4246
|
deadline = asyncio.get_running_loop().time() + timeout
|
|
4247
|
+
startup_completed = False
|
|
4236
4248
|
|
|
4237
4249
|
self._begin_run()
|
|
4238
4250
|
try:
|
|
@@ -4241,6 +4253,7 @@ class Worker:
|
|
|
4241
4253
|
finally:
|
|
4242
4254
|
self._registration_done.set()
|
|
4243
4255
|
|
|
4256
|
+
startup_completed = True
|
|
4244
4257
|
if self._stop.is_set():
|
|
4245
4258
|
raise asyncio.CancelledError
|
|
4246
4259
|
background_tasks.append(asyncio.create_task(self._heartbeat_loop()))
|
|
@@ -4262,6 +4275,11 @@ class Worker:
|
|
|
4262
4275
|
run_until_loop, timeout=max(0.0, deadline - asyncio.get_running_loop().time()),
|
|
4263
4276
|
)
|
|
4264
4277
|
except asyncio.TimeoutError as error:
|
|
4278
|
+
if not startup_completed:
|
|
4279
|
+
raise TimeoutError(
|
|
4280
|
+
f"worker {self.worker_id} startup did not finish within the "
|
|
4281
|
+
f"{timeout}s workflow wait budget for {workflow_id}"
|
|
4282
|
+
) from error
|
|
4265
4283
|
raise TimeoutError(f"workflow {workflow_id} not terminal after {timeout}s") from error
|
|
4266
4284
|
finally:
|
|
4267
4285
|
primary_error = sys.exc_info()[1]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: durable-workflow
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.8
|
|
4
4
|
Summary: Python client and worker SDK for Durable Workflow Cloud and self-hosted Server
|
|
5
5
|
Author: Durable Workflow Contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -155,12 +155,15 @@ capabilities with Server at startup. Use stable `2.x` SDK and Server channels
|
|
|
155
155
|
for new applications. The [compatibility guide](https://durable-workflow.com/docs/2.0/compatibility/)
|
|
156
156
|
documents protocol and upgrade guarantees.
|
|
157
157
|
|
|
158
|
-
##
|
|
158
|
+
## Worker protocol and cooperative cancellation
|
|
159
|
+
|
|
160
|
+
Workers use protocol 1.20 by default. For a Server that supports only 1.19, set
|
|
161
|
+
`DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION=1.19`. This changes the request protocol
|
|
162
|
+
without enabling optional worker features.
|
|
159
163
|
|
|
160
164
|
Use `request_cancellation()` for bounded, replayable workflow cleanup. Opt in
|
|
161
165
|
against a Server that advertises protocol 1.20 and the required capabilities:
|
|
162
|
-
|
|
163
|
-
`cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
166
|
+
include `cooperative_cancellation` in the Worker's `capabilities`. Durable local callback
|
|
164
167
|
admission also needs `prepared_local_activities`, with
|
|
165
168
|
`prepared_local_activity_cancellation_policies` for explicit local policies.
|
|
166
169
|
Independently cancellable scopes remain disabled.
|
|
@@ -196,11 +199,10 @@ to true. CI verifies that checkout, builds the candidate Server, enables protoco
|
|
|
196
199
|
authority and exact source provenance. An optional exact `native_commit` mounts
|
|
197
200
|
that public Native checkout read-only into the test stack. The image's published
|
|
198
201
|
Composer authority stays intact and the evidence identifies the source overlay.
|
|
199
|
-
These are source qualification runs. For a local
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
keeps protocol 1.19 and skips this unpublished feature's connected cases.
|
|
202
|
+
These are source qualification runs. For a local candidate, set
|
|
203
|
+
`DURABLE_WORKFLOW_COOPERATIVE_QUALIFICATION=1` for pytest. These cases fail if the
|
|
204
|
+
runtime does not discover the required capability. Ordinary CI uses the SDK's
|
|
205
|
+
default protocol and skips the optional connected cooperative cases.
|
|
204
206
|
|
|
205
207
|
## License
|
|
206
208
|
|
|
@@ -152,8 +152,8 @@ async def test_invalid_authority_fails_before_io(change: dict[str, Any]) -> None
|
|
|
152
152
|
send.assert_not_awaited()
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
async def
|
|
156
|
-
monkeypatch.
|
|
155
|
+
async def test_previous_protocol_refuses_opening_before_io(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
156
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "1.19")
|
|
157
157
|
async with Client("http://server", namespace="tenant") as client:
|
|
158
158
|
with patch.object(client, "_request", new_callable=AsyncMock) as send:
|
|
159
159
|
with pytest.raises(ValueError, match="1.20"):
|
|
@@ -164,10 +164,15 @@ class TestHeaders:
|
|
|
164
164
|
|
|
165
165
|
def test_worker_headers(self, client: Client) -> None:
|
|
166
166
|
h = client._headers(worker=True)
|
|
167
|
-
assert PROTOCOL_VERSION == "1.
|
|
167
|
+
assert PROTOCOL_VERSION == "1.20"
|
|
168
168
|
assert h["X-Durable-Workflow-Protocol-Version"] == PROTOCOL_VERSION
|
|
169
169
|
assert "X-Durable-Workflow-Control-Plane-Version" not in h
|
|
170
170
|
|
|
171
|
+
def test_explicit_previous_worker_protocol(self, client: Client, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
172
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "1.19")
|
|
173
|
+
assert client._headers(worker=True)["X-Durable-Workflow-Protocol-Version"] == "1.19"
|
|
174
|
+
assert client._headers(worker=False)["X-Durable-Workflow-Control-Plane-Version"] == "2"
|
|
175
|
+
|
|
171
176
|
def test_conformance_protocol_header_overrides(self, client: Client, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
172
177
|
monkeypatch.setenv("DURABLE_WORKFLOW_CONTROL_PLANE_VERSION", "3")
|
|
173
178
|
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "2.0")
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_cancellation_client.py
RENAMED
|
@@ -406,14 +406,11 @@ async def test_activity_stop_receipt_rejects_invalid_identity_before_io(
|
|
|
406
406
|
|
|
407
407
|
|
|
408
408
|
@pytest.mark.asyncio
|
|
409
|
-
@pytest.mark.parametrize("version", [
|
|
410
|
-
async def
|
|
411
|
-
client: Client, monkeypatch: pytest.MonkeyPatch, version: str
|
|
409
|
+
@pytest.mark.parametrize("version", ["1.19", "2.20", "invalid"])
|
|
410
|
+
async def test_activity_stop_receipt_requires_compatible_protocol(
|
|
411
|
+
client: Client, monkeypatch: pytest.MonkeyPatch, version: str,
|
|
412
412
|
) -> None:
|
|
413
|
-
|
|
414
|
-
monkeypatch.delenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", raising=False)
|
|
415
|
-
else:
|
|
416
|
-
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", version)
|
|
413
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", version)
|
|
417
414
|
with patch.object(client._http, "request", new_callable=AsyncMock) as send, pytest.raises(ValueError):
|
|
418
415
|
await client.acknowledge_activity_cancellation(
|
|
419
416
|
task_id="task/1", activity_attempt_id="attempt-1", lease_owner="worker-1", request_id="original-request",
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cooperative_cancellation_worker.py
RENAMED
|
@@ -134,7 +134,7 @@ class ClaimServer:
|
|
|
134
134
|
return {"outcome": "completed"}
|
|
135
135
|
|
|
136
136
|
async def worker(self, monkeypatch: pytest.MonkeyPatch, **kwargs: Any) -> Worker:
|
|
137
|
-
monkeypatch.
|
|
137
|
+
monkeypatch.delenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", raising=False)
|
|
138
138
|
# These transport/replay fixtures use local callbacks that share mock
|
|
139
139
|
# state with this process. They never poll or advertise remote handlers.
|
|
140
140
|
local_callbacks = kwargs.pop("activities", [])
|
|
@@ -94,7 +94,7 @@ async def application_failure(kind: str) -> None:
|
|
|
94
94
|
|
|
95
95
|
@pytest_asyncio.fixture
|
|
96
96
|
async def owner(monkeypatch: pytest.MonkeyPatch): # type: ignore[no-untyped-def]
|
|
97
|
-
monkeypatch.
|
|
97
|
+
monkeypatch.delenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", raising=False)
|
|
98
98
|
client = AsyncMock(spec=Client)
|
|
99
99
|
client.get_cluster_info.return_value = compatible_cluster_info(worker_protocol={
|
|
100
100
|
"version": "1.20", "server_capabilities": {"cooperative_cancellation": True},
|
|
@@ -317,8 +317,8 @@ async def test_client_observation_keeps_worker_credentials_namespace_and_fence(m
|
|
|
317
317
|
assert send.await_args.kwargs["json"] == {"activity_attempt_id": "attempt", "lease_owner": "owner"}
|
|
318
318
|
|
|
319
319
|
|
|
320
|
-
async def
|
|
321
|
-
monkeypatch.
|
|
320
|
+
async def test_client_observation_refuses_previous_protocol_before_io(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
321
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "1.19")
|
|
322
322
|
async with Client("http://runtime.test") as client:
|
|
323
323
|
with (patch.object(client._http, "request", new_callable=AsyncMock) as send,
|
|
324
324
|
pytest.raises(ValueError, match="1.20")):
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_client.py
RENAMED
|
@@ -66,8 +66,8 @@ async def test_invalid_claim_or_authority_never_starts_transport(change: dict[st
|
|
|
66
66
|
send.assert_not_awaited()
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
async def
|
|
70
|
-
monkeypatch.
|
|
69
|
+
async def test_previous_protocol_refuses_before_io(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
70
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "1.19")
|
|
71
71
|
async with Client("http://server") as client:
|
|
72
72
|
with patch.object(client, "_request", new_callable=AsyncMock) as send:
|
|
73
73
|
with pytest.raises(ValueError, match="1.20"):
|
|
@@ -45,13 +45,13 @@ def test_worker_release_identity_matches_supported_server_and_protocol() -> None
|
|
|
45
45
|
assert release["product-train"] == project["version"]
|
|
46
46
|
assert release["registry-version"] == project["version"].replace("-rc.", "rc")
|
|
47
47
|
assert check_release_metadata.VERSION_PATTERN.fullmatch(release["supported-server-versions"]) is not None
|
|
48
|
-
assert release["worker-protocol-version"] == PROTOCOL_VERSION == "1.
|
|
48
|
+
assert release["worker-protocol-version"] == PROTOCOL_VERSION == "1.20"
|
|
49
49
|
assert release["durable-selection"] is True
|
|
50
50
|
assert release["durable-selection-minimum-worker-protocol-version"] == "1.19"
|
|
51
51
|
|
|
52
52
|
assert declared_runtime_protocol_version(
|
|
53
53
|
(REPO_ROOT / "src" / "durable_workflow" / "client.py").read_text(encoding="utf-8")
|
|
54
|
-
) == "1.
|
|
54
|
+
) == "1.20"
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def pypi_json(source: SourceMetadata, **overrides: object) -> bytes:
|
|
@@ -1114,6 +1114,39 @@ class TestWorkerRegistration:
|
|
|
1114
1114
|
await worker._register()
|
|
1115
1115
|
mock_client.register_worker.assert_not_called()
|
|
1116
1116
|
|
|
1117
|
+
@pytest.mark.asyncio
|
|
1118
|
+
async def test_register_accepts_explicit_previous_protocol(
|
|
1119
|
+
self, mock_client: AsyncMock, monkeypatch: pytest.MonkeyPatch,
|
|
1120
|
+
) -> None:
|
|
1121
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", "1.19")
|
|
1122
|
+
mock_client.get_cluster_info = AsyncMock(
|
|
1123
|
+
return_value=compatible_cluster_info(worker_protocol={"version": "1.19"})
|
|
1124
|
+
)
|
|
1125
|
+
worker = Worker(mock_client, task_queue="q1", workflows=[TestWorkflow], activities=[])
|
|
1126
|
+
await worker._register()
|
|
1127
|
+
mock_client.register_worker.assert_called_once()
|
|
1128
|
+
|
|
1129
|
+
@pytest.mark.asyncio
|
|
1130
|
+
async def test_default_protocol_refuses_previous_server_before_registration(self, mock_client: AsyncMock) -> None:
|
|
1131
|
+
mock_client.get_cluster_info = AsyncMock(
|
|
1132
|
+
return_value=compatible_cluster_info(worker_protocol={"version": "1.19"})
|
|
1133
|
+
)
|
|
1134
|
+
worker = Worker(mock_client, task_queue="q1", workflows=[TestWorkflow], activities=[])
|
|
1135
|
+
with pytest.raises(RuntimeError, match="minor>='1.20'"):
|
|
1136
|
+
await worker._register()
|
|
1137
|
+
mock_client.register_worker.assert_not_called()
|
|
1138
|
+
|
|
1139
|
+
@pytest.mark.asyncio
|
|
1140
|
+
@pytest.mark.parametrize("version", ["1.18", "1.21", "2.0"])
|
|
1141
|
+
async def test_register_rejects_unsupported_protocol_override(
|
|
1142
|
+
self, mock_client: AsyncMock, monkeypatch: pytest.MonkeyPatch, version: str,
|
|
1143
|
+
) -> None:
|
|
1144
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", version)
|
|
1145
|
+
worker = Worker(mock_client, task_queue="q1", workflows=[TestWorkflow], activities=[])
|
|
1146
|
+
with pytest.raises(RuntimeError, match="supports worker protocol 1.19 or protocol 1.20"):
|
|
1147
|
+
await worker._register()
|
|
1148
|
+
mock_client.register_worker.assert_not_called()
|
|
1149
|
+
|
|
1117
1150
|
@pytest.mark.asyncio
|
|
1118
1151
|
async def test_register_accepts_higher_compatible_minor_protocol(self, mock_client: AsyncMock) -> None:
|
|
1119
1152
|
# Server is one minor ahead of the SDK. MINOR bumps in workflow:v2's
|
|
@@ -5068,6 +5101,34 @@ class TestRunUntil:
|
|
|
5068
5101
|
assert mock_client.describe_workflow.await_count == 2
|
|
5069
5102
|
assert mock_client.poll_workflow_task.call_args.kwargs["history_page_size"] == 500
|
|
5070
5103
|
|
|
5104
|
+
@pytest.mark.asyncio
|
|
5105
|
+
@pytest.mark.parametrize("blocked_method", ["get_cluster_info", "register_worker"])
|
|
5106
|
+
async def test_run_until_identifies_startup_timeout_before_polling(
|
|
5107
|
+
self, mock_client: AsyncMock, blocked_method: str
|
|
5108
|
+
) -> None:
|
|
5109
|
+
started = asyncio.Event()
|
|
5110
|
+
|
|
5111
|
+
async def blocked(*args: object, **kwargs: object) -> None:
|
|
5112
|
+
started.set()
|
|
5113
|
+
await asyncio.Event().wait()
|
|
5114
|
+
|
|
5115
|
+
setattr(mock_client, blocked_method, AsyncMock(side_effect=blocked))
|
|
5116
|
+
worker = Worker(mock_client, task_queue="q1", workflows=[TestWorkflow])
|
|
5117
|
+
|
|
5118
|
+
with pytest.raises(TimeoutError) as failure:
|
|
5119
|
+
await worker.run_until(workflow_id="wf-startup-timeout", timeout=0.05)
|
|
5120
|
+
|
|
5121
|
+
assert started.is_set()
|
|
5122
|
+
assert "startup" in str(failure.value)
|
|
5123
|
+
assert worker.worker_id in str(failure.value)
|
|
5124
|
+
assert "wf-startup-timeout" in str(failure.value)
|
|
5125
|
+
assert isinstance(failure.value.__cause__, asyncio.TimeoutError)
|
|
5126
|
+
assert worker._stop.is_set()
|
|
5127
|
+
assert worker._registration_done.is_set()
|
|
5128
|
+
mock_client.poll_workflow_task.assert_not_awaited()
|
|
5129
|
+
mock_client.poll_activity_task.assert_not_awaited()
|
|
5130
|
+
mock_client.deregister_worker_registration.assert_not_awaited()
|
|
5131
|
+
|
|
5071
5132
|
@pytest.mark.asyncio
|
|
5072
5133
|
async def test_run_until_times_out_and_stops_worker(self, mock_client: AsyncMock) -> None:
|
|
5073
5134
|
mock_client.describe_workflow = AsyncMock(
|
|
@@ -5086,9 +5147,11 @@ class TestRunUntil:
|
|
|
5086
5147
|
poll_timeout=0.01,
|
|
5087
5148
|
)
|
|
5088
5149
|
|
|
5089
|
-
with pytest.raises(TimeoutError, match="wf-timeout"):
|
|
5150
|
+
with pytest.raises(TimeoutError, match="wf-timeout") as failure:
|
|
5090
5151
|
await worker.run_until(workflow_id="wf-timeout", timeout=0.02, poll_interval=0.01)
|
|
5091
5152
|
|
|
5153
|
+
assert "not terminal" in str(failure.value)
|
|
5154
|
+
assert "startup" not in str(failure.value)
|
|
5092
5155
|
assert worker._stop.is_set()
|
|
5093
5156
|
|
|
5094
5157
|
@pytest.mark.asyncio
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_cancellation_scope.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_cooperative_cancellation.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_prepared_local_activity.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/_sticky_workflow_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/external_task_input.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/external_task_result.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/history_bundle_verify.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/python_conformance.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow/replay_conformance.py
RENAMED
|
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
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/requires.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/src/durable_workflow.egg-info/top_level.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_activity_cancellation_policies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_admission.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_cancellation_scope_authoring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_groups.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_history.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_committed_cancellation_scope_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_control_plane_parity_fixtures.py
RENAMED
|
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
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_parallel_completion_order_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_groups.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_policies.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_prepared_local_activity_worker.py
RENAMED
|
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
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_run_cancellation_scope_replay.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_runtime_external_payload_transport.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_scoped_run_cancellation_context.py
RENAMED
|
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
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_update_signal_condition_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_entrypoint_validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.6 → durable_workflow-2.5.8}/tests/test_workflow_updates_conformance.py
RENAMED
|
File without changes
|