durable-workflow 2.3.5__tar.gz → 2.3.7__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.3.5/src/durable_workflow.egg-info → durable_workflow-2.3.7}/PKG-INFO +1 -1
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/pyproject.toml +3 -3
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/external_storage.py +1 -1
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/worker.py +14 -14
- {durable_workflow-2.3.5 → durable_workflow-2.3.7/src/durable_workflow.egg-info}/PKG-INFO +1 -1
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_external_storage.py +21 -1
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_replay_regression_corpus.py +50 -2
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_worker.py +27 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/LICENSE +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/README.md +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/setup.cfg +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/__init__.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/_avro.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/activity.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/auth_composition.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/client.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/errors.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/external_task_input.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/external_task_result.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/history_bundle_verify.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/interceptors.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/invocable.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/metrics.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/nexus.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/py.typed +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/python_conformance.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/replay_conformance.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/replay_verify.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/retry_policy.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/serializer.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/sync.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/testing.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/worker_session.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/workflow.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/workflow_updates_conformance.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/SOURCES.txt +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/dependency_links.txt +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/entry_points.txt +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/requires.txt +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/top_level.txt +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_activity_context.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_auth_composition.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_avro_value_benchmark.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_avro_value_protocol.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_ci_checkout.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_ci_integration_endpoint.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_client.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_codec_regression_corpus.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_control_plane_parity_fixtures.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_docstring_cross_references.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_durable_selection.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_errors.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_external_task_input.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_external_task_result.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_golden_history_replay.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_history_bundle_verify.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_history_event_contract.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_invocable.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_message_streams.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_metrics.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_order_processing_example.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_parallel_completion_order_replay.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_parallel_saga_authoring.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_public_boundary_scanner.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_pypi_project_surface.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_python_conformance.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_queries.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_readme_quickstart.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_redrive_replay.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_release_metadata.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_replay.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_replay_conformance.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_replay_verify.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_retry_policy.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_runtime_external_payload_transport.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_schedules.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_serializer.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_signals.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_sleep.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_standalone_activity_client.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_storage_admission.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_sync.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_testing_harness.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_update_signal_condition_replay.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_updates.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_wait_condition.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_worker_session.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_workflow_result_timeout.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_workflow_streams.py +0 -0
- {durable_workflow-2.3.5 → durable_workflow-2.3.7}/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.3.
|
|
7
|
+
version = "2.3.7"
|
|
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.3.
|
|
75
|
-
registry-version = "2.3.
|
|
74
|
+
product-train = "2.3.7"
|
|
75
|
+
registry-version = "2.3.7"
|
|
76
76
|
supported-server-versions = "2.4.8"
|
|
77
77
|
worker-protocol-version = "1.19"
|
|
78
78
|
control-plane-version = "2"
|
|
@@ -250,7 +250,7 @@ class ExternalPayloadCache:
|
|
|
250
250
|
contract as a fresh driver fetch.
|
|
251
251
|
"""
|
|
252
252
|
|
|
253
|
-
def __init__(self, *, max_entries: int =
|
|
253
|
+
def __init__(self, *, max_entries: int = 1024, max_bytes: int = 16 * 1024 * 1024) -> None:
|
|
254
254
|
if max_entries < 1:
|
|
255
255
|
raise ValueError("external payload cache max_entries must be at least 1")
|
|
256
256
|
if max_bytes < 1:
|
|
@@ -98,6 +98,7 @@ from .workflow import (
|
|
|
98
98
|
log = logging.getLogger("durable_workflow.worker")
|
|
99
99
|
|
|
100
100
|
QUERY_TASKS_CAPABILITY = "query_tasks"
|
|
101
|
+
WORKFLOW_HISTORY_PAGE_SIZE = 500
|
|
101
102
|
UPDATE_VALIDATION_TASKS_CAPABILITY = "update_validation_tasks"
|
|
102
103
|
WORKFLOW_UPDATES_CAPABILITY = "workflow_updates"
|
|
103
104
|
MESSAGE_STREAMS_CAPABILITY = "message_streams"
|
|
@@ -1637,22 +1638,19 @@ class Worker:
|
|
|
1637
1638
|
wf_type: str = task.get("workflow_type", "")
|
|
1638
1639
|
history = task.get("history_events", [])
|
|
1639
1640
|
|
|
1640
|
-
#
|
|
1641
|
+
# The worker requests bounded history pages when polling. Do not replay
|
|
1642
|
+
# an incomplete history if fetching a later page fails.
|
|
1641
1643
|
next_page_token = task.get("next_history_page_token")
|
|
1642
1644
|
while next_page_token:
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
next_page_token = page_data.get("next_history_page_token") if page_data else None
|
|
1653
|
-
except Exception as e:
|
|
1654
|
-
log.warning("failed to fetch history page for task %s: %s", task_id, e)
|
|
1655
|
-
break
|
|
1645
|
+
page_data = await self.client.workflow_task_history(
|
|
1646
|
+
task_id=task_id,
|
|
1647
|
+
next_history_page_token=next_page_token,
|
|
1648
|
+
lease_owner=self.worker_id,
|
|
1649
|
+
workflow_task_attempt=attempt,
|
|
1650
|
+
)
|
|
1651
|
+
if page_data and page_data.get("history_events"):
|
|
1652
|
+
history.extend(page_data["history_events"])
|
|
1653
|
+
next_page_token = page_data.get("next_history_page_token") if page_data else None
|
|
1656
1654
|
|
|
1657
1655
|
start_input: list[Any] = []
|
|
1658
1656
|
codec = task.get("payload_codec")
|
|
@@ -2535,6 +2533,7 @@ class Worker:
|
|
|
2535
2533
|
timeout=self._poll_http_timeout,
|
|
2536
2534
|
build_id=self.build_id,
|
|
2537
2535
|
task_kinds=self._workflow_poll_task_kinds(),
|
|
2536
|
+
history_page_size=WORKFLOW_HISTORY_PAGE_SIZE,
|
|
2538
2537
|
)
|
|
2539
2538
|
except asyncio.CancelledError:
|
|
2540
2539
|
self._release_workflow_capacity()
|
|
@@ -3224,6 +3223,7 @@ class Worker:
|
|
|
3224
3223
|
timeout=self._poll_http_timeout,
|
|
3225
3224
|
build_id=self.build_id,
|
|
3226
3225
|
task_kinds=self._workflow_poll_task_kinds(),
|
|
3226
|
+
history_page_size=WORKFLOW_HISTORY_PAGE_SIZE,
|
|
3227
3227
|
)
|
|
3228
3228
|
except BaseException:
|
|
3229
3229
|
self._release_workflow_capacity()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from unittest.mock import AsyncMock
|
|
3
|
+
from unittest.mock import AsyncMock, patch
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
@@ -740,6 +740,26 @@ def test_fetch_external_payload_cache_reuses_verified_bytes(tmp_path: Path) -> N
|
|
|
740
740
|
assert len(cache) == 1
|
|
741
741
|
|
|
742
742
|
|
|
743
|
+
def test_default_cache_reuses_large_replay_reference_set(tmp_path: Path) -> None:
|
|
744
|
+
storage = LocalFilesystemExternalStorage(tmp_path)
|
|
745
|
+
cache = ExternalPayloadCache()
|
|
746
|
+
references = [
|
|
747
|
+
store_external_payload(storage, f"signal-{index}".encode(), codec="avro")
|
|
748
|
+
for index in range(1000)
|
|
749
|
+
]
|
|
750
|
+
|
|
751
|
+
with patch.object(storage, "get", wraps=storage.get) as get:
|
|
752
|
+
for _ in range(2):
|
|
753
|
+
for index, reference in enumerate(references):
|
|
754
|
+
assert fetch_external_payload(storage, reference, cache=cache) == (
|
|
755
|
+
f"signal-{index}".encode()
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
assert get.call_count == len(references)
|
|
759
|
+
assert len(cache) == len(references)
|
|
760
|
+
assert cache.current_bytes <= cache.max_bytes == 16 * 1024 * 1024
|
|
761
|
+
|
|
762
|
+
|
|
743
763
|
def test_delete_external_payload_removes_blob_and_cache_entry(tmp_path: Path) -> None:
|
|
744
764
|
storage = LocalFilesystemExternalStorage(tmp_path)
|
|
745
765
|
cache = ExternalPayloadCache(max_entries=2, max_bytes=1024)
|
|
@@ -4,11 +4,12 @@ import json
|
|
|
4
4
|
from collections.abc import Mapping, Sequence
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
|
+
from unittest.mock import AsyncMock
|
|
7
8
|
|
|
8
9
|
import pytest
|
|
9
10
|
|
|
10
|
-
from durable_workflow import Replayer, serializer, workflow
|
|
11
|
-
from durable_workflow.client import WorkflowStreamAppendItem
|
|
11
|
+
from durable_workflow import Replayer, Worker, serializer, workflow
|
|
12
|
+
from durable_workflow.client import Client, WorkflowStreamAppendItem
|
|
12
13
|
from durable_workflow.errors import NonDeterministicReplayError, WorkflowPayloadDecodeError
|
|
13
14
|
from durable_workflow.workflow import WorkflowContext, commands_to_server_commands, query_state
|
|
14
15
|
from tests.test_golden_history_replay import (
|
|
@@ -156,6 +157,17 @@ class RecordedSideEffectWorkflow:
|
|
|
156
157
|
return (yield ctx.side_effect(unexpected_execution))
|
|
157
158
|
|
|
158
159
|
|
|
160
|
+
@workflow.defn(name="tests.replay.paged-recorded-side-effects")
|
|
161
|
+
class PagedRecordedSideEffectsWorkflow:
|
|
162
|
+
def run(self, ctx: WorkflowContext): # type: ignore[no-untyped-def]
|
|
163
|
+
def unexpected_execution() -> int:
|
|
164
|
+
raise AssertionError("recorded side effect callable ran during replay")
|
|
165
|
+
|
|
166
|
+
first = yield ctx.side_effect(unexpected_execution)
|
|
167
|
+
second = yield ctx.side_effect(unexpected_execution)
|
|
168
|
+
return first + second
|
|
169
|
+
|
|
170
|
+
|
|
159
171
|
@workflow.defn(name="tests.replay.message-stream-consumer")
|
|
160
172
|
class MessageStreamConsumerWorkflow:
|
|
161
173
|
def run(self, ctx: WorkflowContext): # type: ignore[no-untyped-def]
|
|
@@ -212,6 +224,7 @@ WORKFLOWS = [
|
|
|
212
224
|
NestedParallelPathWorkflow,
|
|
213
225
|
ParallelMetadataProducerWorkflow,
|
|
214
226
|
ParallelResultBindingWorkflow,
|
|
227
|
+
PagedRecordedSideEffectsWorkflow,
|
|
215
228
|
PostConditionReceiversWorkflow,
|
|
216
229
|
RecordedSideEffectWorkflow,
|
|
217
230
|
SelectionAwaitMarkerWorkflow,
|
|
@@ -394,6 +407,41 @@ def test_checked_in_replay_regression_corpus_uses_official_replayer(
|
|
|
394
407
|
_execute_fixture(fixture)
|
|
395
408
|
|
|
396
409
|
|
|
410
|
+
@pytest.mark.asyncio
|
|
411
|
+
async def test_worker_replays_recorded_side_effects_across_history_pages() -> None:
|
|
412
|
+
fixture = json.loads((FIXTURE_DIR / "paged-recorded-side-effects.json").read_text(encoding="utf-8"))
|
|
413
|
+
history = fixture["history"]
|
|
414
|
+
client = AsyncMock(spec=Client)
|
|
415
|
+
client.workflow_task_history.return_value = {
|
|
416
|
+
"history_events": history[1:],
|
|
417
|
+
"next_history_page_token": None,
|
|
418
|
+
}
|
|
419
|
+
worker = Worker(client, task_queue="paged-history", workflows=[PagedRecordedSideEffectsWorkflow])
|
|
420
|
+
|
|
421
|
+
commands = await worker._run_workflow_task_core({
|
|
422
|
+
"task_id": "task-paged-side-effects",
|
|
423
|
+
"workflow_id": "workflow-paged-side-effects",
|
|
424
|
+
"run_id": "run-paged-side-effects",
|
|
425
|
+
"workflow_type": fixture["workflow"]["type"],
|
|
426
|
+
"workflow_task_attempt": 1,
|
|
427
|
+
"history_events": history[:1],
|
|
428
|
+
"next_history_page_token": "second-page",
|
|
429
|
+
"arguments": serializer.encode([], codec="avro"),
|
|
430
|
+
"payload_codec": "avro",
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
client.workflow_task_history.assert_awaited_once_with(
|
|
434
|
+
task_id="task-paged-side-effects",
|
|
435
|
+
next_history_page_token="second-page",
|
|
436
|
+
lease_owner=worker.worker_id,
|
|
437
|
+
workflow_task_attempt=1,
|
|
438
|
+
)
|
|
439
|
+
client.complete_workflow_task.assert_awaited_once()
|
|
440
|
+
assert commands is not None
|
|
441
|
+
assert [command["type"] for command in commands] == ["complete_workflow"]
|
|
442
|
+
assert serializer.decode_envelope(commands[0]["result"]) == 198
|
|
443
|
+
|
|
444
|
+
|
|
397
445
|
@pytest.mark.parametrize(
|
|
398
446
|
"fixture",
|
|
399
447
|
[
|
|
@@ -836,6 +836,7 @@ class TestWorkerRegistration:
|
|
|
836
836
|
workflow_kwargs = mock_client.poll_workflow_task.call_args.kwargs
|
|
837
837
|
assert workflow_called.is_set()
|
|
838
838
|
assert workflow_kwargs["build_id"] == "release-2026.04.22-a1"
|
|
839
|
+
assert workflow_kwargs["history_page_size"] == 500
|
|
839
840
|
|
|
840
841
|
worker._stop.clear()
|
|
841
842
|
mock_client.poll_activity_task.side_effect = activity_poll_once
|
|
@@ -1189,6 +1190,31 @@ class TestWorkerRegistration:
|
|
|
1189
1190
|
|
|
1190
1191
|
|
|
1191
1192
|
class TestWorkflowTaskExecution:
|
|
1193
|
+
@pytest.mark.asyncio
|
|
1194
|
+
async def test_history_page_failure_does_not_replay_partial_history(
|
|
1195
|
+
self, mock_client: AsyncMock
|
|
1196
|
+
) -> None:
|
|
1197
|
+
mock_client.workflow_task_history.side_effect = RuntimeError("history page unavailable")
|
|
1198
|
+
worker = Worker(mock_client, task_queue="q1", workflows=[TestWorkflow])
|
|
1199
|
+
task = {
|
|
1200
|
+
"task_id": "t-paged-history",
|
|
1201
|
+
"workflow_type": "test-wf",
|
|
1202
|
+
"workflow_task_attempt": 1,
|
|
1203
|
+
"history_events": [{"event_id": "first-page"}],
|
|
1204
|
+
"next_history_page_token": "next-page",
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
with pytest.raises(RuntimeError, match="history page unavailable"):
|
|
1208
|
+
await worker._run_workflow_task_core(task)
|
|
1209
|
+
|
|
1210
|
+
mock_client.workflow_task_history.assert_awaited_once_with(
|
|
1211
|
+
task_id="t-paged-history",
|
|
1212
|
+
next_history_page_token="next-page",
|
|
1213
|
+
lease_owner=worker.worker_id,
|
|
1214
|
+
workflow_task_attempt=1,
|
|
1215
|
+
)
|
|
1216
|
+
mock_client.complete_workflow_task.assert_not_awaited()
|
|
1217
|
+
|
|
1192
1218
|
@pytest.mark.asyncio
|
|
1193
1219
|
async def test_local_activity_runs_in_workflow_worker_and_records_heartbeats(
|
|
1194
1220
|
self, mock_client: AsyncMock
|
|
@@ -4948,6 +4974,7 @@ class TestRunUntil:
|
|
|
4948
4974
|
assert worker._stop.is_set()
|
|
4949
4975
|
mock_client.register_worker.assert_awaited_once()
|
|
4950
4976
|
assert mock_client.describe_workflow.await_count == 2
|
|
4977
|
+
assert mock_client.poll_workflow_task.call_args.kwargs["history_page_size"] == 500
|
|
4951
4978
|
|
|
4952
4979
|
@pytest.mark.asyncio
|
|
4953
4980
|
async def test_run_until_times_out_and_stops_worker(self, mock_client: AsyncMock) -> None:
|
|
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.3.5 → durable_workflow-2.3.7}/src/durable_workflow/external_task_input.py
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow/external_task_result.py
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/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.3.5 → durable_workflow-2.3.7}/src/durable_workflow/python_conformance.py
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/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.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/requires.txt
RENAMED
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/src/durable_workflow.egg-info/top_level.txt
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.3.5 → durable_workflow-2.3.7}/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
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_runtime_external_payload_transport.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.3.5 → durable_workflow-2.3.7}/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
|
{durable_workflow-2.3.5 → durable_workflow-2.3.7}/tests/test_workflow_updates_conformance.py
RENAMED
|
File without changes
|