durable-workflow 2.5.11__tar.gz → 2.5.12__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.11/src/durable_workflow.egg-info → durable_workflow-2.5.12}/PKG-INFO +1 -1
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/pyproject.toml +3 -3
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/client.py +3 -1
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/retry_policy.py +22 -1
- {durable_workflow-2.5.11 → durable_workflow-2.5.12/src/durable_workflow.egg-info}/PKG-INFO +1 -1
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/SOURCES.txt +1 -0
- durable_workflow-2.5.12/tests/test_query_timeout_retry.py +73 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/LICENSE +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/README.md +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/setup.cfg +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/__init__.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_activity_process.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_avro.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_cancellation_scope.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_cancellation_scope_history.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_cooperative_cancellation.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_prepared_local_activity.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_sticky_workflow_cache.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/activity.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/auth_composition.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/cancellation.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/errors.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_storage.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_task_input.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_task_result.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/history_bundle_verify.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/interceptors.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/invocable.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/metrics.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/nexus.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/py.typed +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/python_conformance.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/replay_conformance.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/replay_verify.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/serializer.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/sync.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/testing.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/worker.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/worker_session.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/workflow.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/workflow_updates_conformance.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/dependency_links.txt +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/entry_points.txt +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/requires.txt +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/top_level.txt +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_activity_cancellation_policies.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_activity_context.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_activity_process.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_auth_composition.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_avro_value_benchmark.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_avro_value_protocol.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_context.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_remaining_time.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_admission.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_authoring.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_boundary.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_opening.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_child_workflow_policies.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_ci_checkout.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_ci_integration_endpoint.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_client.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_client_timeouts.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_codec_regression_corpus.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_committed_cancellation_scope_descendants.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_committed_cancellation_scope_groups.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_committed_cancellation_scope_history.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_committed_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_condition_replay_drift.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_control_plane_parity_fixtures.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_cancellation.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_cancellation_client.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_cancellation_worker.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_remote_worker.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_docstring_cross_references.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_durable_selection.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_errors.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_external_storage.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_external_task_input.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_external_task_result.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_golden_history_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_history_bundle_verify.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_history_event_contract.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_invocable.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_message_streams.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_metrics.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_nexus_namespace.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_nexus_wire.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_order_processing_example.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_parallel_completion_order_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_parallel_saga_authoring.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_patch_history.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_pending_operation_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_client.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_groups.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_policies.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_worker.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_public_boundary_scanner.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_pypi_project_surface.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_python_conformance.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_queries.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_readme_quickstart.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_redrive_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_registration_ambiguity.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_release_metadata.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_replay_conformance.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_replay_regression_corpus.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_replay_verify.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_retry_policy.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_run_cancellation_scope_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_runtime_external_payload_transport.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_schedules.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_scoped_run_cancellation_context.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_serializer.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_signals.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_sleep.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_standalone_activity_client.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_sticky_execution.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_storage_admission.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_sync.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_testing_harness.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_update_signal_condition_replay.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_updates.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_wait_condition.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_worker.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_worker_session.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_workflow_entrypoint_validation.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_workflow_result_timeout.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_workflow_streams.py +0 -0
- {durable_workflow-2.5.11 → durable_workflow-2.5.12}/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.5.
|
|
7
|
+
version = "2.5.12"
|
|
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,8 +71,8 @@ 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.12"
|
|
75
|
+
registry-version = "2.5.12"
|
|
76
76
|
supported-server-versions = "2.5.16"
|
|
77
77
|
worker-protocol-version = "1.20"
|
|
78
78
|
control-plane-version = "2"
|
|
@@ -4323,7 +4323,9 @@ class Client:
|
|
|
4323
4323
|
Queries are synchronous and non-mutating. The server runs the named
|
|
4324
4324
|
query handler inside the workflow process and returns the decoded
|
|
4325
4325
|
result. Raises :class:`~durable_workflow.errors.QueryFailed` if the
|
|
4326
|
-
query was rejected or the
|
|
4326
|
+
query was rejected, the handler errored, or the original query timed
|
|
4327
|
+
out. A canonical query timeout is surfaced without automatically
|
|
4328
|
+
admitting another query.
|
|
4327
4329
|
"""
|
|
4328
4330
|
await self._require_query_support()
|
|
4329
4331
|
body: dict[str, Any] = {}
|
|
@@ -17,6 +17,7 @@ import contextvars
|
|
|
17
17
|
import json
|
|
18
18
|
import logging
|
|
19
19
|
import random
|
|
20
|
+
import re
|
|
20
21
|
from collections.abc import Awaitable, Callable
|
|
21
22
|
from dataclasses import dataclass
|
|
22
23
|
from typing import TypeVar
|
|
@@ -34,6 +35,24 @@ _worker_storage_admission_stop: contextvars.ContextVar[Callable[[], bool] | None
|
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
|
|
38
|
+
def _query_timeout_refusal(exc: httpx.HTTPStatusError) -> bool:
|
|
39
|
+
request = exc.request
|
|
40
|
+
if (exc.response.status_code != 504 or request.method != "POST"
|
|
41
|
+
or request.headers.get("X-Durable-Workflow-Control-Plane-Version") != "2"
|
|
42
|
+
or re.search(r"/api/workflows/[^/]+/query/[^/]+$", request.url.path) is None):
|
|
43
|
+
return False
|
|
44
|
+
try:
|
|
45
|
+
body = exc.response.json()
|
|
46
|
+
except ValueError:
|
|
47
|
+
return False
|
|
48
|
+
# This response ends an admitted query. Another POST creates a new task,
|
|
49
|
+
# rather than retrying the original task or its remaining caller budget.
|
|
50
|
+
reason = body.get("reason") if isinstance(body, dict) else None
|
|
51
|
+
return isinstance(reason, str) and reason in {
|
|
52
|
+
"query_worker_timeout", "query_worker_execution_timeout", "query_task_not_claimed",
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
37
56
|
def _storage_refusal(exc: Exception) -> tuple[ServerError, str | None] | None:
|
|
38
57
|
if not isinstance(exc, httpx.HTTPStatusError):
|
|
39
58
|
return None
|
|
@@ -194,6 +213,8 @@ class TransportRetryPolicy:
|
|
|
194
213
|
:class:`durable_workflow.workflow.ChildWorkflowRetryPolicy`.
|
|
195
214
|
|
|
196
215
|
Uses exponential backoff with jitter to avoid thundering herd.
|
|
216
|
+
Canonical query timeouts end the original query and are surfaced without
|
|
217
|
+
another query admission; unrelated transient HTTP failures still retry.
|
|
197
218
|
"""
|
|
198
219
|
|
|
199
220
|
max_attempts: int = 3
|
|
@@ -213,7 +234,7 @@ class TransportRetryPolicy:
|
|
|
213
234
|
|
|
214
235
|
# Retry 5xx server errors and 429 rate limit
|
|
215
236
|
if isinstance(exc, httpx.HTTPStatusError):
|
|
216
|
-
if _poll_capacity_refusal(exc):
|
|
237
|
+
if _query_timeout_refusal(exc) or _poll_capacity_refusal(exc):
|
|
217
238
|
return False
|
|
218
239
|
return exc.response.status_code >= 500 or exc.response.status_code == 429
|
|
219
240
|
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/SOURCES.txt
RENAMED
|
@@ -95,6 +95,7 @@ tests/test_public_boundary_scanner.py
|
|
|
95
95
|
tests/test_pypi_project_surface.py
|
|
96
96
|
tests/test_python_conformance.py
|
|
97
97
|
tests/test_queries.py
|
|
98
|
+
tests/test_query_timeout_retry.py
|
|
98
99
|
tests/test_readme_quickstart.py
|
|
99
100
|
tests/test_redrive_replay.py
|
|
100
101
|
tests/test_registration_ambiguity.py
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from durable_workflow import Client
|
|
7
|
+
from durable_workflow.errors import QueryFailed
|
|
8
|
+
from durable_workflow.retry_policy import TransportRetryPolicy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.parametrize("protocol", ["1.20", "1.19"])
|
|
12
|
+
@pytest.mark.parametrize("reason", [
|
|
13
|
+
"query_worker_execution_timeout", "query_task_not_claimed", "query_worker_timeout",
|
|
14
|
+
])
|
|
15
|
+
@pytest.mark.parametrize("prefix", ["", "/api/runtime/v1/namespaces/example"])
|
|
16
|
+
async def test_query_exposes_original_canonical_timeout_without_another_admission(
|
|
17
|
+
monkeypatch: pytest.MonkeyPatch, protocol: str, reason: str, prefix: str,
|
|
18
|
+
) -> None:
|
|
19
|
+
monkeypatch.setenv("DURABLE_WORKFLOW_WORKER_PROTOCOL_VERSION", protocol)
|
|
20
|
+
original = {"reason": reason, "message": "Original query ended.",
|
|
21
|
+
"control_plane": {"operation": "query", "reason": reason}}
|
|
22
|
+
admissions = 0
|
|
23
|
+
discovery_protocols = []
|
|
24
|
+
|
|
25
|
+
def handle(request: httpx.Request) -> httpx.Response:
|
|
26
|
+
nonlocal admissions
|
|
27
|
+
if request.url.path.endswith("/api/cluster/info"):
|
|
28
|
+
discovery_protocols.append(request.headers["X-Durable-Workflow-Protocol-Version"])
|
|
29
|
+
return httpx.Response(200, json={
|
|
30
|
+
"worker_protocol": {"server_capabilities": {"query_tasks": True}},
|
|
31
|
+
})
|
|
32
|
+
assert request.url.path == prefix + "/api/workflows/original/query/total"
|
|
33
|
+
assert request.headers["X-Durable-Workflow-Control-Plane-Version"] == "2"
|
|
34
|
+
admissions += 1
|
|
35
|
+
if admissions == 1:
|
|
36
|
+
return httpx.Response(504, json=original)
|
|
37
|
+
# The old policy hides the original failure behind a distinct admission.
|
|
38
|
+
return httpx.Response(200, json={"result": "replacement-query"})
|
|
39
|
+
|
|
40
|
+
async with Client("https://runtime.example" + prefix, worker_token="worker", control_token="control",
|
|
41
|
+
retry_policy=TransportRetryPolicy(initial_backoff_seconds=0, jitter=False)) as client:
|
|
42
|
+
await client._http.aclose()
|
|
43
|
+
client._http = httpx.AsyncClient(base_url=client.base_url, transport=httpx.MockTransport(handle))
|
|
44
|
+
with pytest.raises(QueryFailed) as failure:
|
|
45
|
+
await client.query_workflow("original", "total")
|
|
46
|
+
assert admissions == 1
|
|
47
|
+
assert discovery_protocols == [protocol]
|
|
48
|
+
assert failure.value.status == 504 and failure.value.reason == reason
|
|
49
|
+
assert failure.value.body == original
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.parametrize(("method", "path", "status", "body", "headers"), [
|
|
53
|
+
("POST", "/api/workflows/w/query/q", 504, {"reason": "gateway_timeout"},
|
|
54
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
55
|
+
("POST", "/api/workflows/w/query/q", 503, {"reason": "query_worker_timeout"},
|
|
56
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
57
|
+
("GET", "/api/workflows/w/query/q", 504, {"reason": "query_worker_timeout"},
|
|
58
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
59
|
+
("POST", "/api/workflows/w/signals/q", 504, {"reason": "query_worker_timeout"},
|
|
60
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
61
|
+
("POST", "/api/workflows/w/query/q", 504, {"reason": "query_worker_timeout"}, {}),
|
|
62
|
+
("POST", "/api/workflows/w/query/q", 504, [],
|
|
63
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
64
|
+
("POST", "/api/workflows/w/query/q", 504, {"reason": []},
|
|
65
|
+
{"X-Durable-Workflow-Control-Plane-Version": "2"}),
|
|
66
|
+
])
|
|
67
|
+
def test_other_transport_failures_keep_existing_retry_policy(
|
|
68
|
+
method: str, path: str, status: int, body: object, headers: dict[str, str],
|
|
69
|
+
) -> None:
|
|
70
|
+
request = httpx.Request(method, "https://runtime.example" + path, headers=headers)
|
|
71
|
+
response = httpx.Response(status, request=request, json=body)
|
|
72
|
+
error = httpx.HTTPStatusError("transport failure", request=request, response=response)
|
|
73
|
+
assert TransportRetryPolicy().should_retry(error, 0) is True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_activity_process.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_cancellation_scope.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_prepared_local_activity.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/_sticky_workflow_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/auth_composition.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_storage.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_task_input.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow/external_task_result.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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.11 → durable_workflow-2.5.12}/src/durable_workflow/python_conformance.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/requires.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/src/durable_workflow.egg-info/top_level.txt
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_remaining_time.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_admission.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_authoring.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cancellation_scope_boundary.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_control_plane_parity_fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_cancellation_client.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_cooperative_cancellation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_parallel_completion_order_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_client.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_groups.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_prepared_local_activity_policies.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/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
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_run_cancellation_scope_replay.py
RENAMED
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_runtime_external_payload_transport.py
RENAMED
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_scoped_run_cancellation_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_standalone_activity_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_update_signal_condition_replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_workflow_entrypoint_validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.5.11 → durable_workflow-2.5.12}/tests/test_workflow_updates_conformance.py
RENAMED
|
File without changes
|