durable-workflow 2.12.0__tar.gz → 2.12.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.
- {durable_workflow-2.12.0/src/durable_workflow.egg-info → durable_workflow-2.12.1}/PKG-INFO +1 -1
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/pyproject.toml +3 -3
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/workflow.py +15 -1
- {durable_workflow-2.12.0 → durable_workflow-2.12.1/src/durable_workflow.egg-info}/PKG-INFO +1 -1
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_replay_regression_corpus.py +2 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_wait_condition.py +41 -1
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/LICENSE +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/README.md +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/setup.cfg +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/__init__.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_activity_lease.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_activity_process.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_avro.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_cancellation_scope.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_cancellation_scope_history.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_cooperative_cancellation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_failure_reporting.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_metric_routes.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_poll_transport.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_prepared_local_activity.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_query_task_authority.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_sticky_workflow_cache.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/activity.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/auth_composition.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/cancellation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/client.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/errors.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_storage.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_task_input.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_task_result.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/history_bundle_verify.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/interceptors.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/invocable.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/metrics.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/nexus.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/py.typed +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/python_conformance.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/replay_conformance.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/replay_verify.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/retry_policy.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/serializer.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/sync.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/telemetry.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/telemetry_carrier.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/testing.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/worker_session.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/workflow_updates_conformance.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/SOURCES.txt +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/dependency_links.txt +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/entry_points.txt +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/requires.txt +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/top_level.txt +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_cancellation_policies.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_context.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_heartbeat_authority.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_lease_authority.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_lease_renewal.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_lease_worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_process.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_retry_info.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_auth_composition.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_avro_value_benchmark.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_avro_value_protocol.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_context.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_remaining_time.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_admission.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_authoring.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_boundary.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_opening.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_child_workflow_policies.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_ci_checkout.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_ci_integration_endpoint.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_client.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_client_telemetry.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_client_timeouts.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_codec_regression_corpus.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_committed_cancellation_scope_descendants.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_committed_cancellation_scope_groups.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_committed_cancellation_scope_history.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_committed_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_condition_replay_drift.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_control_plane_parity_fixtures.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_cancellation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_cancellation_client.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_cancellation_worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_remote_worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_docstring_cross_references.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_durable_selection.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_errors.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_external_storage.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_external_task_input.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_external_task_result.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_failure_reporting.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_golden_history_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_history_bundle_schema2.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_history_bundle_verify.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_history_event_contract.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_invocable.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_local_failure_reporting.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_message_streams.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_metric_routes.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_metrics.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_nexus_durable_wait.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_nexus_namespace.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_nexus_wire.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_order_processing_example.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_parallel_completion_order_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_parallel_saga_authoring.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_patch_history.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_pending_operation_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_poll_failure_backoff.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_poll_transport.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_client.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_groups.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_policies.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_public_boundary_scanner.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_pypi_project_surface.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_python_conformance.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_queries.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_query_task_authority.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_query_timeout_retry.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_readme_quickstart.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_redrive_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_registration_ambiguity.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_release_metadata.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_replay_clock.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_replay_conformance.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_replay_verify.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_retry_policy.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_run_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_runtime_external_payload_transport.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_schedules.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_scoped_run_cancellation_context.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_sdk_metrics_contract.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_serializer.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_signals.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_sleep.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_standalone_activity_client.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_sticky_execution.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_storage_admission.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_sync.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_sync_activities.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_telemetry.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_telemetry_carrier.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_testing_failures.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_testing_harness.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_testing_nexus.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_threaded_heartbeat_example.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_tls_trust.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_transport_diagnostics.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_update_signal_condition_replay.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_updates.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_worker.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_worker_deregistration.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_worker_observation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_worker_session.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_worker_telemetry_wire.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_entry_arguments.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_entrypoint_validation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_handler_validation.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_identity.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_result_timeout.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_streams.py +0 -0
- {durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_updates_conformance.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "durable-workflow"
|
|
7
|
-
version = "2.12.
|
|
7
|
+
version = "2.12.1"
|
|
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"
|
|
@@ -76,8 +76,8 @@ durable-workflow-replay-conformance = "durable_workflow.replay_conformance:main"
|
|
|
76
76
|
durable-workflow-workflow-updates-conformance = "durable_workflow.workflow_updates_conformance:main"
|
|
77
77
|
|
|
78
78
|
[tool.durable-workflow]
|
|
79
|
-
product-train = "2.12.
|
|
80
|
-
registry-version = "2.12.
|
|
79
|
+
product-train = "2.12.1"
|
|
80
|
+
registry-version = "2.12.1"
|
|
81
81
|
supported-server-versions = "2.8.0"
|
|
82
82
|
worker-protocol-version = "1.20"
|
|
83
83
|
control-plane-version = "2"
|
|
@@ -4661,6 +4661,7 @@ def _replay_state(
|
|
|
4661
4661
|
# Receiver replay uses this exact boundary so interleaved input is applied
|
|
4662
4662
|
# in durable order without leaking input recorded after the terminal row.
|
|
4663
4663
|
condition_wait_terminal_indexes: dict[str, int] = {}
|
|
4664
|
+
condition_wait_opened_indexes: dict[str, int] = {}
|
|
4664
4665
|
# Selection members are bound by their durable sequence instead of being
|
|
4665
4666
|
# inserted into the ordinary completion-order cursor. This is what lets a
|
|
4666
4667
|
# loser complete before or after unrelated successor work without changing
|
|
@@ -5006,6 +5007,7 @@ def _replay_state(
|
|
|
5006
5007
|
wait_id = payload.get("condition_wait_id")
|
|
5007
5008
|
if not isinstance(wait_id, str) or not wait_id:
|
|
5008
5009
|
continue
|
|
5010
|
+
condition_wait_opened_indexes.setdefault(wait_id, index)
|
|
5009
5011
|
|
|
5010
5012
|
if current_wait_id is None:
|
|
5011
5013
|
for receiver_index in prefix_receivers:
|
|
@@ -5070,7 +5072,14 @@ def _replay_state(
|
|
|
5070
5072
|
|
|
5071
5073
|
for receiver_index in receivers_since_wait:
|
|
5072
5074
|
if receiver_index is not None and receiver_index not in bindings:
|
|
5073
|
-
|
|
5075
|
+
if boundary_kind == "condition":
|
|
5076
|
+
# A terminal row can precede the next physical reopen.
|
|
5077
|
+
# Later inputs admitted during the first receiver's
|
|
5078
|
+
# leased replay belong to that reopen, not the wait
|
|
5079
|
+
# already resolved by the first receiver.
|
|
5080
|
+
prefix_receivers.append(receiver_index)
|
|
5081
|
+
else:
|
|
5082
|
+
bindings[receiver_index] = current_wait_id
|
|
5074
5083
|
current_wait_id = None
|
|
5075
5084
|
receivers_since_wait = []
|
|
5076
5085
|
prefix_can_bind_to_first_wait = boundary_kind == "condition"
|
|
@@ -5431,6 +5440,11 @@ def _replay_state(
|
|
|
5431
5440
|
terminal_index = condition_wait_terminal_indexes.get(condition_wait_id)
|
|
5432
5441
|
if terminal_index is not None:
|
|
5433
5442
|
while pending_receivers and pending_receivers[0].history_index < terminal_index:
|
|
5443
|
+
receiver_wait_id = pending_receivers[0].condition_wait_id
|
|
5444
|
+
receiver_wait_index = (condition_wait_opened_indexes.get(receiver_wait_id)
|
|
5445
|
+
if receiver_wait_id is not None else None)
|
|
5446
|
+
if receiver_wait_index is not None and receiver_wait_index > terminal_index:
|
|
5447
|
+
break
|
|
5434
5448
|
_apply_receiver(pending_receivers.pop(0))
|
|
5435
5449
|
return
|
|
5436
5450
|
target_index = next(
|
|
@@ -47,6 +47,7 @@ from tests.test_update_signal_condition_replay import (
|
|
|
47
47
|
PostConditionReceiversWorkflow,
|
|
48
48
|
UpdateSignalConditionTimerWorkflow,
|
|
49
49
|
)
|
|
50
|
+
from tests.test_wait_condition import SignalCounterUntilFinished
|
|
50
51
|
from tests.test_worker import compatible_cluster_info
|
|
51
52
|
from tests.test_workflow_identity import IdentityAcrossReplay, IdentityContinueAsNew
|
|
52
53
|
|
|
@@ -375,6 +376,7 @@ WORKFLOWS = [
|
|
|
375
376
|
FencedRecoveryWorkflow,
|
|
376
377
|
PagedRecordedSideEffectsWorkflow,
|
|
377
378
|
PostConditionReceiversWorkflow,
|
|
379
|
+
SignalCounterUntilFinished,
|
|
378
380
|
RecordedSideEffectWorkflow,
|
|
379
381
|
SelectionAwaitMarkerWorkflow,
|
|
380
382
|
SelectionCancellationQueryWorkflow,
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
5
|
from durable_workflow import serializer, workflow
|
|
6
|
-
from durable_workflow.errors import NonDeterministicReplayError
|
|
6
|
+
from durable_workflow.errors import NonDeterministicReplayError, QueryFailed
|
|
7
7
|
from durable_workflow.workflow import (
|
|
8
8
|
CompleteWorkflow,
|
|
9
9
|
WaitCondition,
|
|
@@ -567,6 +567,46 @@ class TestReplayWaitCondition:
|
|
|
567
567
|
assert outcome.commands[0].result == expected
|
|
568
568
|
assert query_state(SignalCounterUntilFinished, history, [], "current") == expected
|
|
569
569
|
|
|
570
|
+
@pytest.mark.parametrize("receiver_sequence", [None, 1])
|
|
571
|
+
@pytest.mark.parametrize("changed_identity", [None, "condition_key", "condition_definition_fingerprint"])
|
|
572
|
+
def test_signal_during_condition_completion_keeps_its_physical_reopen(
|
|
573
|
+
self, receiver_sequence: int | None, changed_identity: str | None,
|
|
574
|
+
) -> None:
|
|
575
|
+
history = [
|
|
576
|
+
{"event_type": "ConditionWaitOpened", "payload": {
|
|
577
|
+
"condition_wait_id": "wait-first", "condition_key": "done", "sequence": 1,
|
|
578
|
+
}},
|
|
579
|
+
_signal_received_event("increment", [3], workflow_sequence=receiver_sequence),
|
|
580
|
+
_signal_received_event("finish", [], workflow_sequence=receiver_sequence),
|
|
581
|
+
{"event_type": "SignalApplied", "payload": {"signal_name": "increment"}},
|
|
582
|
+
{"event_type": "ConditionWaitSatisfied", "payload": {
|
|
583
|
+
"condition_wait_id": "wait-first", "condition_key": "done", "sequence": 1,
|
|
584
|
+
}},
|
|
585
|
+
{"event_type": "ConditionWaitOpened", "payload": {
|
|
586
|
+
"condition_wait_id": "wait-reopened", "condition_key": "done", "sequence": 2,
|
|
587
|
+
}},
|
|
588
|
+
]
|
|
589
|
+
|
|
590
|
+
if changed_identity is not None:
|
|
591
|
+
history[-1]["payload"][changed_identity] = "changed-definition"
|
|
592
|
+
with pytest.raises(NonDeterministicReplayError, match="ConditionWaitOpened") as captured:
|
|
593
|
+
replay(SignalCounterUntilFinished, history, [])
|
|
594
|
+
assert captured.value.workflow_sequence == 2
|
|
595
|
+
with pytest.raises(QueryFailed, match="ConditionWaitOpened") as query_error:
|
|
596
|
+
query_state(SignalCounterUntilFinished, history, [], "current")
|
|
597
|
+
assert isinstance(query_error.value.__cause__, NonDeterministicReplayError)
|
|
598
|
+
assert query_error.value.__cause__.workflow_sequence == 2
|
|
599
|
+
return
|
|
600
|
+
|
|
601
|
+
expected = {"count": 3, "done": True, "events": [
|
|
602
|
+
{"signal": "increment", "amount": 3, "count": 3}, {"signal": "finish", "count": 3},
|
|
603
|
+
]}
|
|
604
|
+
outcome = replay(SignalCounterUntilFinished, history, [])
|
|
605
|
+
assert len(outcome.commands) == 1
|
|
606
|
+
assert isinstance(outcome.commands[0], CompleteWorkflow)
|
|
607
|
+
assert outcome.commands[0].result == expected
|
|
608
|
+
assert query_state(SignalCounterUntilFinished, history, [], "current") == expected
|
|
609
|
+
|
|
570
610
|
def test_signal_received_before_reopened_wait_uses_next_wait_when_sequence_absent(self) -> None:
|
|
571
611
|
history = [
|
|
572
612
|
{
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_activity_process.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_cancellation_scope.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_failure_reporting.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_prepared_local_activity.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_query_task_authority.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/_sticky_workflow_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/auth_composition.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_storage.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_task_input.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/external_task_result.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/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.12.0 → durable_workflow-2.12.1}/src/durable_workflow/python_conformance.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/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
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow/telemetry_carrier.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/requires.txt
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/src/durable_workflow.egg-info/top_level.txt
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_cancellation_policies.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_activity_heartbeat_authority.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.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_remaining_time.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_admission.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_authoring.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_boundary.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cancellation_scope_opening.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.12.0 → durable_workflow-2.12.1}/tests/test_control_plane_parity_fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_cancellation_client.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_cooperative_cancellation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_docstring_cross_references.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_parallel_completion_order_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_client.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_groups.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_prepared_local_activity_policies.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_run_cancellation_scope_replay.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_runtime_external_payload_transport.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_scoped_run_cancellation_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_standalone_activity_client.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.12.0 → durable_workflow-2.12.1}/tests/test_threaded_heartbeat_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_update_signal_condition_replay.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.12.0 → durable_workflow-2.12.1}/tests/test_workflow_entrypoint_validation.py
RENAMED
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_handler_validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.12.0 → durable_workflow-2.12.1}/tests/test_workflow_updates_conformance.py
RENAMED
|
File without changes
|