harness-sdk-python 0.13.0__tar.gz → 0.13.2__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.
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/PKG-INFO +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/pyproject.toml +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/src/harness_sdk/run_manager.py +24 -35
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_ack_visibility.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_batches.py +8 -14
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_branch_anchor.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_dispatching.py +2 -2
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_edit_dispatched.py +4 -4
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_edit_reload.py +7 -7
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_enqueue.py +3 -3
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_input_required.py +5 -5
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_meta.py +2 -2
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_outcomes.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_prepare_hooks.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_restore.py +2 -2
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_rewind_during_run.py +6 -6
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_settle.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_steer.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_stop_continue.py +1 -1
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_stopping_window.py +32 -34
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/.gitignore +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/README.md +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/examples/__init__.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/examples/runs_app.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/src/harness_sdk/__init__.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/src/harness_sdk/fenced_postgres.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/src/harness_sdk/linear_thread.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/run_helpers.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_fenced_postgres.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_linear_thread.py +0 -0
- {harness_sdk_python-0.13.0 → harness_sdk_python-0.13.2}/tests/test_placement.py +0 -0
|
@@ -10,10 +10,10 @@ dispatchable send appends straight into ``dispatching`` — it never transits a
|
|
|
10
10
|
queue lane — and everything staged there by the end of the drain dispatches
|
|
11
11
|
as one run; in error/stop the dispatch is the continuation
|
|
12
12
|
(``error-continue`` / ``stop-continue``) carrying the send's messages. Every
|
|
13
|
-
initiator acks and settles accepted with its state-visible application
|
|
14
|
-
sends with their insert (lane
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
initiator acks and settles accepted with its state-visible application:
|
|
14
|
+
the verdict certifies the admission write — sends with their insert (lane
|
|
15
|
+
or ``dispatching``), mid-run edit/reload with the stopping window,
|
|
16
|
+
``run/stop`` with ``stopping`` — never future execution.
|
|
17
17
|
|
|
18
18
|
``entry["dispatching"]`` is the dispatch record (absent between an ack and
|
|
19
19
|
the next dispatch or take): the payload the run callback receives.
|
|
@@ -25,8 +25,8 @@ A mid-run stop or rewind opens a stopping window on the entry:
|
|
|
25
25
|
``stopping: {reason}`` plus, for rewinds, the staged dispatch as
|
|
26
26
|
``nextDispatch`` — written in the same envelope as the opener's pending
|
|
27
27
|
answer. On run end one envelope promotes ``nextDispatch`` into
|
|
28
|
-
``dispatching`` and clears the window; a later stop/rewind
|
|
29
|
-
staged
|
|
28
|
+
``dispatching`` and clears the window; a later stop/rewind replaces the
|
|
29
|
+
staged dispatch, whose command already settled at its admission write.
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
import asyncio
|
|
@@ -53,9 +53,9 @@ _CAPABILITIES = frozenset(
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
_TRIGGERS = (
|
|
56
|
-
"send
|
|
57
|
-
"edit
|
|
58
|
-
"reload
|
|
56
|
+
"message-send",
|
|
57
|
+
"message-edit",
|
|
58
|
+
"message-reload",
|
|
59
59
|
"input-resume",
|
|
60
60
|
"error-continue",
|
|
61
61
|
"stop-continue",
|
|
@@ -209,7 +209,7 @@ class RunManager:
|
|
|
209
209
|
self._dispatch_record: dict[str, Any] | None = None
|
|
210
210
|
self._intake: list[Any] = []
|
|
211
211
|
self._outcome: Any = None
|
|
212
|
-
self.
|
|
212
|
+
self._stop_staged = False
|
|
213
213
|
self._stop_reason: str | None = None
|
|
214
214
|
self._staged_rewind: _Rewind | None = None
|
|
215
215
|
self._dispatching: list[tuple[str, dict[str, Any]]] = []
|
|
@@ -354,10 +354,7 @@ class RunManager:
|
|
|
354
354
|
for entry in entries:
|
|
355
355
|
self._apply(entry, fx)
|
|
356
356
|
if self._task is None:
|
|
357
|
-
|
|
358
|
-
if not stop.done():
|
|
359
|
-
stop.set_result(None)
|
|
360
|
-
self._staged_stops.clear()
|
|
357
|
+
self._stop_staged = False
|
|
361
358
|
if isinstance(outcome, RunManager.Complete):
|
|
362
359
|
self._dispatched_ids = ()
|
|
363
360
|
if self._staged_rewind is not None:
|
|
@@ -378,14 +375,12 @@ class RunManager:
|
|
|
378
375
|
)
|
|
379
376
|
if not rewind.acked:
|
|
380
377
|
rewind.ack()
|
|
381
|
-
if not rewind.future.done():
|
|
382
|
-
rewind.future.set_result(None)
|
|
383
378
|
elif outcome is not None:
|
|
384
379
|
self._settle_outcome(outcome)
|
|
385
380
|
else:
|
|
386
381
|
self._idle_action(fx)
|
|
387
382
|
if self._task is not None and (
|
|
388
|
-
self.
|
|
383
|
+
self._stop_staged or self._staged_rewind is not None
|
|
389
384
|
):
|
|
390
385
|
assert self._ctx is not None
|
|
391
386
|
self._ctx.stop_requested.set()
|
|
@@ -401,12 +396,14 @@ class RunManager:
|
|
|
401
396
|
|
|
402
397
|
def _apply(self, entry: Any, fx: _Effects) -> None:
|
|
403
398
|
if isinstance(entry, _Stop):
|
|
404
|
-
self._staged_stops.append(entry.future)
|
|
405
399
|
if self._task is not None:
|
|
400
|
+
self._stop_staged = True
|
|
406
401
|
if self._staged_rewind is not None:
|
|
407
|
-
self.
|
|
402
|
+
self._staged_rewind = None
|
|
408
403
|
self._entry().pop("nextDispatch", None)
|
|
409
404
|
self._entry()["stopping"] = {"reason": "stop"}
|
|
405
|
+
if not entry.future.done():
|
|
406
|
+
entry.future.set_result(None)
|
|
410
407
|
return
|
|
411
408
|
if isinstance(entry, _Continue):
|
|
412
409
|
if not fx.continue_requested:
|
|
@@ -641,7 +638,7 @@ class RunManager:
|
|
|
641
638
|
|
|
642
639
|
def _send_trigger(self) -> str:
|
|
643
640
|
status = self._status()
|
|
644
|
-
return self._continue_type() if status in ("error", "stopped") else "send
|
|
641
|
+
return self._continue_type() if status in ("error", "stopped") else "message-send"
|
|
645
642
|
|
|
646
643
|
def _stage_dispatch(self, e: _Send) -> None:
|
|
647
644
|
assert e.message is not None
|
|
@@ -673,27 +670,17 @@ class RunManager:
|
|
|
673
670
|
if steer:
|
|
674
671
|
self._entry()["steerQueue"] = []
|
|
675
672
|
self._dispatching = [("steerQueue", item) for item in steer]
|
|
676
|
-
self._dispatch("send
|
|
673
|
+
self._dispatch("message-send", steer, input_outcomes=input_outcomes)
|
|
677
674
|
return True
|
|
678
675
|
queue = self._lane_items("queue")
|
|
679
676
|
if queue:
|
|
680
677
|
self._entry()["queue"].pop(0)
|
|
681
678
|
self._dispatching = [("queue", queue[0])]
|
|
682
|
-
self._dispatch("send
|
|
679
|
+
self._dispatch("message-send", [queue[0]], input_outcomes=input_outcomes)
|
|
683
680
|
return True
|
|
684
681
|
return False
|
|
685
682
|
|
|
686
|
-
def _supersede(self) -> None:
|
|
687
|
-
rewind, self._staged_rewind = self._staged_rewind, None
|
|
688
|
-
assert rewind is not None
|
|
689
|
-
if not rewind.future.done():
|
|
690
|
-
rewind.future.set_exception(
|
|
691
|
-
_reject("superseded", "a later stop/rewind replaced this command")
|
|
692
|
-
)
|
|
693
|
-
|
|
694
683
|
def _stage_rewind(self, rewind: _Rewind) -> None:
|
|
695
|
-
if self._staged_rewind is not None:
|
|
696
|
-
self._supersede()
|
|
697
684
|
self._staged_rewind = rewind
|
|
698
685
|
if self._task is not None:
|
|
699
686
|
entry = self._entry()
|
|
@@ -706,6 +693,8 @@ class RunManager:
|
|
|
706
693
|
)
|
|
707
694
|
rewind.ack()
|
|
708
695
|
rewind.acked = True
|
|
696
|
+
if not rewind.future.done():
|
|
697
|
+
rewind.future.set_result(None)
|
|
709
698
|
|
|
710
699
|
def _freeze(self, message: str, payload: Any = None) -> None:
|
|
711
700
|
self._set_status("error")
|
|
@@ -989,7 +978,7 @@ class RunManager:
|
|
|
989
978
|
self._check_anchor(e)
|
|
990
979
|
self._stage_rewind(
|
|
991
980
|
_Rewind(
|
|
992
|
-
"edit
|
|
981
|
+
"message-edit",
|
|
993
982
|
[self._stamped(e.message, e.meta)],
|
|
994
983
|
e.source_meta["parentId"],
|
|
995
984
|
e.ack,
|
|
@@ -1044,7 +1033,7 @@ class RunManager:
|
|
|
1044
1033
|
)
|
|
1045
1034
|
self._stage_rewind(
|
|
1046
1035
|
_Rewind(
|
|
1047
|
-
"edit
|
|
1036
|
+
"message-edit",
|
|
1048
1037
|
[self._stamped(e.message, e.meta)],
|
|
1049
1038
|
e.source_meta["parentId"],
|
|
1050
1039
|
e.ack,
|
|
@@ -1057,7 +1046,7 @@ class RunManager:
|
|
|
1057
1046
|
def _apply_reload(self, e: _Reload) -> Any:
|
|
1058
1047
|
self._stage_rewind(
|
|
1059
1048
|
_Rewind(
|
|
1060
|
-
"reload
|
|
1049
|
+
"message-reload",
|
|
1061
1050
|
[],
|
|
1062
1051
|
e.source_meta["parentId"],
|
|
1063
1052
|
e.ack,
|
|
@@ -91,7 +91,7 @@ async def test_rewind_edit_acks_with_its_dispatch():
|
|
|
91
91
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
92
92
|
seq = drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
93
93
|
rerun = await script.next_call()
|
|
94
|
-
assert rerun.ctx.trigger == "edit
|
|
94
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
95
95
|
await drv.wait_status("running")
|
|
96
96
|
assert dispatching_ids(covered_state(drv, seq)) == ["u2"]
|
|
97
97
|
host.live.state["messages"] = [msg("u2")]
|
|
@@ -21,7 +21,7 @@ async def test_multi_steer_batch_places_all_and_dispatches_once():
|
|
|
21
21
|
]
|
|
22
22
|
)
|
|
23
23
|
call = await script.next_call()
|
|
24
|
-
assert call.ctx.trigger == "send
|
|
24
|
+
assert call.ctx.trigger == "message-send"
|
|
25
25
|
assert [m["id"] for m in call.ctx.messages] == ["s1", "s2", "s3"]
|
|
26
26
|
script.no_call()
|
|
27
27
|
assert queue_ids(drv.replica, "steerQueue") == []
|
|
@@ -59,30 +59,24 @@ async def test_steer_and_stop_in_one_batch_nets_to_stop():
|
|
|
59
59
|
[("run/steer", add("s1")), ("run/stop", {"runId": await drv.run_id()})]
|
|
60
60
|
)
|
|
61
61
|
assert (await drv.res(first))["type"] == "accepted"
|
|
62
|
-
assert (await drv.res(first + 1
|
|
62
|
+
assert (await drv.res(first + 1))["type"] == "accepted"
|
|
63
63
|
await asyncio.wait_for(call.ctx.stop_requested.wait(), 5)
|
|
64
64
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
65
|
-
assert (await drv.res(first + 1))["type"] == "accepted"
|
|
66
65
|
await drv.wait_status("stopped")
|
|
67
66
|
assert queue_ids(drv.replica, "steerQueue") == ["s1"]
|
|
68
67
|
script.no_call()
|
|
69
68
|
|
|
70
69
|
|
|
71
|
-
async def
|
|
70
|
+
async def test_stop_settles_at_the_stopping_write():
|
|
72
71
|
script = Script()
|
|
73
72
|
async with run_host(script) as (drv, host):
|
|
74
73
|
drv.post("run/enqueue", add("m1"))
|
|
75
74
|
call = await script.next_call()
|
|
76
75
|
call.ack()
|
|
77
|
-
|
|
78
|
-
assert
|
|
79
|
-
|
|
80
|
-
await asyncio.sleep(0)
|
|
81
|
-
assert all(
|
|
82
|
-
rsp["type"] == "pending" for rsp in drv._res.get(pending["seq"], [])
|
|
83
|
-
)
|
|
76
|
+
settled = await drv.stop()
|
|
77
|
+
assert settled["type"] == "accepted"
|
|
78
|
+
assert drv.replica["status"] == "running"
|
|
84
79
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
85
|
-
assert (await drv.res(pending["seq"]))["type"] == "accepted"
|
|
86
80
|
await drv.wait_status("stopped")
|
|
87
81
|
|
|
88
82
|
|
|
@@ -146,7 +140,7 @@ async def test_rewind_outranks_send_and_continue_in_one_batch():
|
|
|
146
140
|
]
|
|
147
141
|
)
|
|
148
142
|
rerun = await script.next_call()
|
|
149
|
-
assert rerun.ctx.trigger == "edit
|
|
143
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
150
144
|
assert [m["id"] for m in rerun.ctx.messages] == ["m2"]
|
|
151
145
|
script.no_call()
|
|
152
146
|
assert (await drv.res(first))["type"] == "accepted"
|
|
@@ -173,7 +167,7 @@ async def test_send_outranks_the_completing_input_answer():
|
|
|
173
167
|
]
|
|
174
168
|
)
|
|
175
169
|
run = await script.next_call()
|
|
176
|
-
assert run.ctx.trigger == "send
|
|
170
|
+
assert run.ctx.trigger == "message-send"
|
|
177
171
|
assert [m["id"] for m in run.ctx.messages] == ["s1"]
|
|
178
172
|
assert run.ctx.input_outcomes == ((request, {"output": "ok"}, None),)
|
|
179
173
|
script.no_call()
|
|
@@ -196,7 +196,7 @@ async def test_post_reload_sends_anchor_on_the_reload_targets_parent():
|
|
|
196
196
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
197
197
|
drv.post("run/reload", reload_params("a1", anchor="u1"))
|
|
198
198
|
call = await script.next_call()
|
|
199
|
-
assert call.ctx.trigger == "reload
|
|
199
|
+
assert call.ctx.trigger == "message-reload"
|
|
200
200
|
call.ack()
|
|
201
201
|
script.thread["a1"] = {
|
|
202
202
|
"parentId": "u1", "role": "assistant", "isLeaf": True, "onActiveBranch": False
|
|
@@ -58,7 +58,7 @@ async def test_idle_send_dispatches_straight_into_dispatching():
|
|
|
58
58
|
drv.post("run/enqueue", add("m1"))
|
|
59
59
|
await script.next_call()
|
|
60
60
|
await drv.wait_status("running")
|
|
61
|
-
assert drv.run["dispatching"]["trigger"] == "send
|
|
61
|
+
assert drv.run["dispatching"]["trigger"] == "message-send"
|
|
62
62
|
assert dispatching_ids(drv.replica) == ["m1"]
|
|
63
63
|
assert queue_ids(drv.replica, "queue") == []
|
|
64
64
|
assert residence(drv, "m1") == ["dispatching"]
|
|
@@ -119,7 +119,7 @@ async def test_edit_replacement_rides_dispatching_until_ack():
|
|
|
119
119
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
120
120
|
seq = drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
121
121
|
rerun = await script.next_call()
|
|
122
|
-
assert rerun.ctx.trigger == "edit
|
|
122
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
123
123
|
await drv.wait_status("running")
|
|
124
124
|
assert dispatching_ids(drv.replica) == ["u2"]
|
|
125
125
|
host.live.state["messages"] = [msg("u2")]
|
|
@@ -19,7 +19,7 @@ async def test_edit_of_dispatched_item_stops_rewinds_reruns(command):
|
|
|
19
19
|
await drv.wait_status("running")
|
|
20
20
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
21
21
|
rerun = await script.next_call()
|
|
22
|
-
assert rerun.ctx.trigger == "edit
|
|
22
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
23
23
|
assert [m["parts"][0]["text"] for m in rerun.ctx.messages] == ["edited"]
|
|
24
24
|
assert rerun.ctx.has_rollback
|
|
25
25
|
assert rerun.ctx.rollback_to == "p0"
|
|
@@ -54,7 +54,7 @@ async def test_edit_of_dispatched_non_leaf_stops_and_reruns(command):
|
|
|
54
54
|
seq = drv.post(command, target(message=msg("m1", "edited")))
|
|
55
55
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
56
56
|
rerun = await script.next_call()
|
|
57
|
-
assert rerun.ctx.trigger == "edit
|
|
57
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
58
58
|
assert [m["parts"][0]["text"] for m in rerun.ctx.messages] == ["edited"]
|
|
59
59
|
rerun.ack()
|
|
60
60
|
rerun.finish(RunManager.Stop(dispatch_queue=False))
|
|
@@ -72,7 +72,7 @@ async def test_edit_of_dispatched_item_with_queued_items_stops_and_reruns():
|
|
|
72
72
|
seq = drv.post("run/enqueue", target(message=msg("m1", "edited")))
|
|
73
73
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
74
74
|
rerun = await script.next_call()
|
|
75
|
-
assert rerun.ctx.trigger == "edit
|
|
75
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
76
76
|
rerun.ack()
|
|
77
77
|
rerun.finish(RunManager.Stop(dispatch_queue=False))
|
|
78
78
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
@@ -90,5 +90,5 @@ async def test_edit_of_dispatched_item_in_error_reruns_without_stop():
|
|
|
90
90
|
await drv.wait_status("error")
|
|
91
91
|
drv.post("run/enqueue", target(message=msg("m1", "edited")))
|
|
92
92
|
rerun = await script.next_call()
|
|
93
|
-
assert rerun.ctx.trigger == "edit
|
|
93
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
94
94
|
assert rerun.ctx.rollback_to is None
|
|
@@ -27,7 +27,7 @@ async def test_edit_in_ready_dispatches_message_edit():
|
|
|
27
27
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
28
28
|
drv.post("run/edit", edit_params("u1", msg("u2", "v2"), anchor=None))
|
|
29
29
|
call = await script.next_call()
|
|
30
|
-
assert call.ctx.trigger == "edit
|
|
30
|
+
assert call.ctx.trigger == "message-edit"
|
|
31
31
|
assert [m["id"] for m in call.ctx.messages] == ["u2"]
|
|
32
32
|
assert call.ctx.has_rollback
|
|
33
33
|
assert call.ctx.rollback_to is None
|
|
@@ -71,7 +71,7 @@ async def test_deep_edit_with_queue_non_empty_reruns_and_keeps_queue():
|
|
|
71
71
|
await drv.wait_status("error")
|
|
72
72
|
drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
73
73
|
rerun = await script.next_call()
|
|
74
|
-
assert rerun.ctx.trigger == "edit
|
|
74
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
75
75
|
assert rerun.ctx.rollback_to is None
|
|
76
76
|
assert [item["id"] for item in drv.run["queue"]] == ["m2"]
|
|
77
77
|
|
|
@@ -88,7 +88,7 @@ async def test_leaf_edit_in_error_accepted_with_queue_non_empty():
|
|
|
88
88
|
await drv.wait_status("error")
|
|
89
89
|
drv.post("run/edit", edit_params("m1", msg("u2"), anchor=None))
|
|
90
90
|
call = await script.next_call()
|
|
91
|
-
assert call.ctx.trigger == "edit
|
|
91
|
+
assert call.ctx.trigger == "message-edit"
|
|
92
92
|
assert call.ctx.rollback_to is None
|
|
93
93
|
assert [item["id"] for item in drv.run["queue"]] == ["m2"]
|
|
94
94
|
|
|
@@ -140,7 +140,7 @@ async def test_reload_dispatches_with_empty_messages():
|
|
|
140
140
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
141
141
|
drv.post("run/reload", reload_params("a1", anchor="u1"))
|
|
142
142
|
call = await script.next_call()
|
|
143
|
-
assert call.ctx.trigger == "reload
|
|
143
|
+
assert call.ctx.trigger == "message-reload"
|
|
144
144
|
assert call.ctx.messages == ()
|
|
145
145
|
assert call.ctx.rollback_to == "u1"
|
|
146
146
|
call.ack()
|
|
@@ -205,7 +205,7 @@ async def test_deep_reload_with_queue_non_empty_reruns_and_keeps_queue():
|
|
|
205
205
|
await drv.wait_status("error")
|
|
206
206
|
drv.post("run/reload", reload_params("a0", anchor="u0"))
|
|
207
207
|
call = await script.next_call()
|
|
208
|
-
assert call.ctx.trigger == "reload
|
|
208
|
+
assert call.ctx.trigger == "message-reload"
|
|
209
209
|
assert call.ctx.rollback_to == "u0"
|
|
210
210
|
assert [item["id"] for item in drv.run["queue"]] == ["m2"]
|
|
211
211
|
|
|
@@ -260,7 +260,7 @@ async def test_edit_anchor_assertion():
|
|
|
260
260
|
script.no_call()
|
|
261
261
|
drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
262
262
|
call = await script.next_call()
|
|
263
|
-
assert call.ctx.trigger == "edit
|
|
263
|
+
assert call.ctx.trigger == "message-edit"
|
|
264
264
|
assert call.ctx.rollback_to is None
|
|
265
265
|
|
|
266
266
|
|
|
@@ -283,5 +283,5 @@ async def test_reload_anchor_assertion():
|
|
|
283
283
|
script.no_call()
|
|
284
284
|
drv.post("run/reload", reload_params("a1", anchor="u1"))
|
|
285
285
|
call = await script.next_call()
|
|
286
|
-
assert call.ctx.trigger == "reload
|
|
286
|
+
assert call.ctx.trigger == "message-reload"
|
|
287
287
|
assert call.ctx.rollback_to == "u1"
|
|
@@ -9,7 +9,7 @@ async def test_ready_add_dispatches_message_send():
|
|
|
9
9
|
async with run_host(script) as (drv, host):
|
|
10
10
|
seq = drv.post("run/enqueue", add("m1"))
|
|
11
11
|
call = await script.next_call()
|
|
12
|
-
assert call.ctx.trigger == "send
|
|
12
|
+
assert call.ctx.trigger == "message-send"
|
|
13
13
|
assert [m["id"] for m in call.ctx.messages] == ["m1"]
|
|
14
14
|
assert not call.ctx.has_rollback
|
|
15
15
|
await drv.wait_status("running")
|
|
@@ -31,7 +31,7 @@ async def test_running_add_becomes_queue_item():
|
|
|
31
31
|
script.no_call()
|
|
32
32
|
call.finish(RunManager.Complete())
|
|
33
33
|
drain = await script.next_call()
|
|
34
|
-
assert drain.ctx.trigger == "send
|
|
34
|
+
assert drain.ctx.trigger == "message-send"
|
|
35
35
|
assert [m["id"] for m in drain.ctx.messages] == ["m2"]
|
|
36
36
|
drain.ack()
|
|
37
37
|
drain.finish(RunManager.Complete())
|
|
@@ -69,7 +69,7 @@ async def test_steer_lane_drains_first_and_whole():
|
|
|
69
69
|
await drv.command("run/steer", add("s2"), terminal=False)
|
|
70
70
|
call.finish(RunManager.Complete())
|
|
71
71
|
steered = await script.next_call()
|
|
72
|
-
assert steered.ctx.trigger == "send
|
|
72
|
+
assert steered.ctx.trigger == "message-send"
|
|
73
73
|
assert [m["id"] for m in steered.ctx.messages] == ["s1", "s2"]
|
|
74
74
|
steered.ack()
|
|
75
75
|
steered.finish(RunManager.Complete())
|
|
@@ -322,7 +322,7 @@ async def test_edit_while_parked_clears_requests_and_reruns():
|
|
|
322
322
|
await park(drv, script, [tool_call("r1")], anchor="a1")
|
|
323
323
|
drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
324
324
|
rerun = await script.next_call()
|
|
325
|
-
assert rerun.ctx.trigger == "edit
|
|
325
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
326
326
|
assert rerun.ctx.rollback_to is None
|
|
327
327
|
await drv.wait(lambda s: "inputRequests" not in run_of(s))
|
|
328
328
|
rerun.ack()
|
|
@@ -337,7 +337,7 @@ async def test_reload_while_parked_clears_requests_and_reruns():
|
|
|
337
337
|
await park(drv, script, [tool_call("r1")], anchor="a1")
|
|
338
338
|
drv.post("run/reload", reload_params("a1", anchor="u1"))
|
|
339
339
|
rerun = await script.next_call()
|
|
340
|
-
assert rerun.ctx.trigger == "reload
|
|
340
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
341
341
|
assert rerun.ctx.rollback_to == "u1"
|
|
342
342
|
await drv.wait(lambda s: "inputRequests" not in run_of(s))
|
|
343
343
|
rerun.ack()
|
|
@@ -351,7 +351,7 @@ async def test_steer_add_while_parked_abandons_input_and_dispatches():
|
|
|
351
351
|
await park(drv, script, [tool_call("r1"), approval("r2")])
|
|
352
352
|
drv.post("run/steer", add("s1"))
|
|
353
353
|
run = await script.next_call()
|
|
354
|
-
assert run.ctx.trigger == "send
|
|
354
|
+
assert run.ctx.trigger == "message-send"
|
|
355
355
|
assert [m["id"] for m in run.ctx.messages] == ["s1"]
|
|
356
356
|
assert run.ctx.input_outcomes == (
|
|
357
357
|
(tool_call("r1"), None, None),
|
|
@@ -394,7 +394,7 @@ async def test_promote_to_steer_while_parked_abandons_input_and_dispatches():
|
|
|
394
394
|
script.no_call()
|
|
395
395
|
await drv.command("run/steer", target(messageId="m2"))
|
|
396
396
|
run = await script.next_call()
|
|
397
|
-
assert run.ctx.trigger == "send
|
|
397
|
+
assert run.ctx.trigger == "message-send"
|
|
398
398
|
assert [m["id"] for m in run.ctx.messages] == ["m2"]
|
|
399
399
|
assert run.ctx.input_outcomes == ((tool_call("r1"), None, None),)
|
|
400
400
|
assert "inputRequests" not in drv.run
|
|
@@ -434,7 +434,7 @@ async def test_steer_add_with_partial_answers_hands_over_the_answered_subset():
|
|
|
434
434
|
)
|
|
435
435
|
drv.post("run/steer", add("s1"))
|
|
436
436
|
run = await script.next_call()
|
|
437
|
-
assert run.ctx.trigger == "send
|
|
437
|
+
assert run.ctx.trigger == "message-send"
|
|
438
438
|
assert [m["id"] for m in run.ctx.messages] == ["s1"]
|
|
439
439
|
assert run.ctx.input_outcomes == (
|
|
440
440
|
(tool_call("r1"), {"output": "ok"}, None),
|
|
@@ -137,7 +137,7 @@ async def test_edit_meta_rides_the_replacement_message():
|
|
|
137
137
|
edit_params("u1", msg("u2", "v2"), anchor=None, meta={"edited": True}),
|
|
138
138
|
)
|
|
139
139
|
call = await script.next_call()
|
|
140
|
-
assert call.ctx.trigger == "edit
|
|
140
|
+
assert call.ctx.trigger == "message-edit"
|
|
141
141
|
assert call.ctx.meta("u2") == {"edited": True}
|
|
142
142
|
assert "meta" not in call.ctx.messages[0]
|
|
143
143
|
assert call.ctx.meta() is None
|
|
@@ -151,7 +151,7 @@ async def test_reload_meta_rides_the_start_root():
|
|
|
151
151
|
async with run_host(script, capabilities=("rewind",)) as (drv, _):
|
|
152
152
|
drv.post("run/reload", reload_params("a1", anchor="u1", meta={"retry": 1}))
|
|
153
153
|
call = await script.next_call()
|
|
154
|
-
assert call.ctx.trigger == "reload
|
|
154
|
+
assert call.ctx.trigger == "message-reload"
|
|
155
155
|
assert call.ctx.meta() == {"retry": 1}
|
|
156
156
|
call.ack()
|
|
157
157
|
call.finish(RunManager.Complete())
|
|
@@ -13,7 +13,7 @@ async def test_register_overwrites_whatever_is_in_the_state():
|
|
|
13
13
|
"error": {"message": "old"},
|
|
14
14
|
"queue": [msg("q1")],
|
|
15
15
|
"steerQueue": [msg("s1")],
|
|
16
|
-
"dispatch": {"type": "send
|
|
16
|
+
"dispatch": {"type": "message-send", "messages": [msg("m1")]},
|
|
17
17
|
}
|
|
18
18
|
async with run_host(script, initial_runs=stale) as (drv, host):
|
|
19
19
|
assert drv.replica == {"status": "ready", "runs": []}
|
|
@@ -94,7 +94,7 @@ async def test_prepare_message_applies_to_edit():
|
|
|
94
94
|
) as (drv, host):
|
|
95
95
|
drv.post("run/edit", edit_params("u1", noisy("u2"), anchor=None))
|
|
96
96
|
call = await script.next_call()
|
|
97
|
-
assert call.ctx.trigger == "edit
|
|
97
|
+
assert call.ctx.trigger == "message-edit"
|
|
98
98
|
assert [m["parts"] for m in call.ctx.messages] == [
|
|
99
99
|
[{"type": "text", "text": "u2"}]
|
|
100
100
|
]
|
|
@@ -89,7 +89,7 @@ async def test_steer_while_hydrated_abandons_input_and_dispatches():
|
|
|
89
89
|
):
|
|
90
90
|
drv.post("run/steer", add("s1"))
|
|
91
91
|
run = await script.next_call()
|
|
92
|
-
assert run.ctx.trigger == "send
|
|
92
|
+
assert run.ctx.trigger == "message-send"
|
|
93
93
|
assert [m["id"] for m in run.ctx.messages] == ["s1"]
|
|
94
94
|
assert run.ctx.input_outcomes == ((tool_call("r1"), None, None),)
|
|
95
95
|
await drv.wait_status("running")
|
|
@@ -114,7 +114,7 @@ async def test_malformed_restore_states_raise():
|
|
|
114
114
|
({"runs": [parked_entry(error={"message": "x"})]}, "error"),
|
|
115
115
|
({"runs": [parked_entry(error=None)]}, "error"),
|
|
116
116
|
({"runs": [parked_entry(stopping={"reason": "stop"})]}, "stopping"),
|
|
117
|
-
({"runs": [parked_entry(nextDispatch={"trigger": "edit
|
|
117
|
+
({"runs": [parked_entry(nextDispatch={"trigger": "message-edit"})]}, "nextDispatch"),
|
|
118
118
|
({"runs": [parked_entry(inputRequests=[])]}, "non-empty list"),
|
|
119
119
|
({"runs": [parked_entry(inputRequests=["nope"])]}, "objects"),
|
|
120
120
|
(
|
|
@@ -33,7 +33,7 @@ async def test_running_leaf_edit_stops_settles_then_rewinds():
|
|
|
33
33
|
await drv.wait_status("running")
|
|
34
34
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
35
35
|
rerun = await script.next_call()
|
|
36
|
-
assert rerun.ctx.trigger == "edit
|
|
36
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
37
37
|
assert [m["id"] for m in rerun.ctx.messages] == ["m2"]
|
|
38
38
|
assert rerun.ctx.rollback_to is None
|
|
39
39
|
rerun.ack()
|
|
@@ -50,7 +50,7 @@ async def test_running_leaf_edit_accepted_with_non_empty_queues():
|
|
|
50
50
|
seq = drv.post("run/edit", edit_params("m1", msg("m2"), anchor=None))
|
|
51
51
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
52
52
|
rerun = await script.next_call()
|
|
53
|
-
assert rerun.ctx.trigger == "edit
|
|
53
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
54
54
|
rerun.ack()
|
|
55
55
|
rerun.finish(RunManager.Stop(dispatch_queue=False))
|
|
56
56
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
@@ -67,7 +67,7 @@ async def test_running_leaf_reload_stops_settles_then_rewinds():
|
|
|
67
67
|
await asyncio.wait_for(call.ctx.stop_requested.wait(), 5)
|
|
68
68
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
69
69
|
rerun = await script.next_call()
|
|
70
|
-
assert rerun.ctx.trigger == "reload
|
|
70
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
71
71
|
assert rerun.ctx.rollback_to == "m1"
|
|
72
72
|
rerun.ack()
|
|
73
73
|
rerun.finish(RunManager.Stop(dispatch_queue=False))
|
|
@@ -97,7 +97,7 @@ async def test_running_non_leaf_edit_stops_settles_then_rewinds():
|
|
|
97
97
|
await asyncio.wait_for(call.ctx.stop_requested.wait(), 5)
|
|
98
98
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
99
99
|
rerun = await script.next_call()
|
|
100
|
-
assert rerun.ctx.trigger == "edit
|
|
100
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
101
101
|
assert [m["id"] for m in rerun.ctx.messages] == ["m2"]
|
|
102
102
|
assert rerun.ctx.rollback_to is None
|
|
103
103
|
rerun.ack()
|
|
@@ -113,7 +113,7 @@ async def test_running_non_leaf_reload_stops_settles_then_rewinds():
|
|
|
113
113
|
await asyncio.wait_for(call.ctx.stop_requested.wait(), 5)
|
|
114
114
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
115
115
|
rerun = await script.next_call()
|
|
116
|
-
assert rerun.ctx.trigger == "reload
|
|
116
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
117
117
|
assert rerun.ctx.rollback_to == "m1"
|
|
118
118
|
rerun.ack()
|
|
119
119
|
rerun.finish(RunManager.Stop(dispatch_queue=False))
|
|
@@ -142,5 +142,5 @@ async def test_leaf_reload_in_error_accepted_with_non_empty_queue():
|
|
|
142
142
|
await drv.wait_status("error")
|
|
143
143
|
drv.post("run/reload", reload_params("a1", anchor="m1"))
|
|
144
144
|
rerun = await script.next_call()
|
|
145
|
-
assert rerun.ctx.trigger == "reload
|
|
145
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
146
146
|
assert queue_ids(drv.replica, "queue") == ["q1"]
|
|
@@ -176,7 +176,7 @@ async def test_rewind_edit_settles_at_its_dispatch():
|
|
|
176
176
|
async with run_host(script, capabilities=("rewind",)) as (drv, host):
|
|
177
177
|
seq = drv.post("run/edit", edit_params("u1", msg("u2"), anchor=None))
|
|
178
178
|
rerun = await script.next_call()
|
|
179
|
-
assert rerun.ctx.trigger == "edit
|
|
179
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
180
180
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
181
181
|
rerun.ack()
|
|
182
182
|
rerun.finish(RunManager.Complete())
|
|
@@ -9,7 +9,7 @@ async def test_ready_steer_add_dispatches_like_enqueue():
|
|
|
9
9
|
async with run_host(script) as (drv, host):
|
|
10
10
|
drv.post("run/steer", add("m1"))
|
|
11
11
|
call = await script.next_call()
|
|
12
|
-
assert call.ctx.trigger == "send
|
|
12
|
+
assert call.ctx.trigger == "message-send"
|
|
13
13
|
assert [m["id"] for m in call.ctx.messages] == ["m1"]
|
|
14
14
|
|
|
15
15
|
|
|
@@ -33,7 +33,7 @@ async def test_stop_outcome_can_keep_the_queue_draining():
|
|
|
33
33
|
await drv.stop(terminal=False)
|
|
34
34
|
call.finish(RunManager.Stop(dispatch_queue=True))
|
|
35
35
|
drain = await script.next_call()
|
|
36
|
-
assert drain.ctx.trigger == "send
|
|
36
|
+
assert drain.ctx.trigger == "message-send"
|
|
37
37
|
assert [m["id"] for m in drain.ctx.messages] == ["m2"]
|
|
38
38
|
await drv.wait_status("running")
|
|
39
39
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""Contract: the stopping window. Three openers — run/stop, mid-run
|
|
2
2
|
edit/reload, and the enqueue/steer edit-of-dispatched form — write
|
|
3
|
-
``stopping: {reason}`` (plus the staged rewind as ``nextDispatch``)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
``stopping: {reason}`` (plus the staged rewind as ``nextDispatch``) and
|
|
4
|
+
settle accepted with that write, ``status`` staying "running". On run end
|
|
5
|
+
one envelope promotes ``nextDispatch`` into ``dispatching`` and clears the
|
|
6
|
+
window; a later stop/rewind replaces the staged dispatch, whose command
|
|
7
|
+
already settled at its admission write."""
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import copy
|
|
@@ -13,7 +13,6 @@ import pytest
|
|
|
13
13
|
from run_helpers import (
|
|
14
14
|
Script,
|
|
15
15
|
add,
|
|
16
|
-
assert_rejected,
|
|
17
16
|
edit_params,
|
|
18
17
|
msg,
|
|
19
18
|
queue_ids,
|
|
@@ -57,23 +56,22 @@ async def start_run(drv, script, *, parent="p0"):
|
|
|
57
56
|
return call
|
|
58
57
|
|
|
59
58
|
|
|
60
|
-
async def
|
|
59
|
+
async def test_stop_opens_the_window_and_settles_with_its_write():
|
|
61
60
|
script = Script()
|
|
62
61
|
async with run_host(script) as (drv, host):
|
|
63
62
|
call = await start_run(drv, script)
|
|
64
|
-
|
|
65
|
-
assert
|
|
63
|
+
settled = await drv.stop()
|
|
64
|
+
assert settled["type"] == "accepted"
|
|
66
65
|
assert drv.replica["status"] == "running"
|
|
67
66
|
assert drv.run["stopping"] == {"reason": "stop"}
|
|
68
67
|
assert "nextDispatch" not in drv.run
|
|
69
68
|
opened = next(
|
|
70
69
|
state
|
|
71
70
|
for env, state in states(drv)
|
|
72
|
-
if any(r["seq"] ==
|
|
71
|
+
if any(r["seq"] == settled["seq"] for r in env.get("res", []))
|
|
73
72
|
)
|
|
74
73
|
assert window_of(opened) == ({"reason": "stop"}, None)
|
|
75
74
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
76
|
-
assert (await drv.res(pending["seq"]))["type"] == "accepted"
|
|
77
75
|
await drv.wait_status("stopped")
|
|
78
76
|
assert "stopping" not in drv.run
|
|
79
77
|
|
|
@@ -89,10 +87,10 @@ async def test_mid_run_edit_stages_the_window_and_promotes_in_one_envelope():
|
|
|
89
87
|
await asyncio.wait_for(call.ctx.stop_requested.wait(), 5)
|
|
90
88
|
await drv.wait(lambda s: "stopping" in (s["runs"] or [{}])[0])
|
|
91
89
|
assert drv.replica["status"] == "running"
|
|
92
|
-
assert drv.run["stopping"] == {"reason": "edit
|
|
90
|
+
assert drv.run["stopping"] == {"reason": "message-edit"}
|
|
93
91
|
staged = drv.run["nextDispatch"]
|
|
94
92
|
assert staged == {
|
|
95
|
-
"trigger": "edit
|
|
93
|
+
"trigger": "message-edit",
|
|
96
94
|
"messages": [msg("m2")],
|
|
97
95
|
"rollbackTo": "p0",
|
|
98
96
|
}
|
|
@@ -101,12 +99,12 @@ async def test_mid_run_edit_stages_the_window_and_promotes_in_one_envelope():
|
|
|
101
99
|
for env, state in states(drv)
|
|
102
100
|
if any(r["seq"] == seq for r in env.get("res", []))
|
|
103
101
|
)
|
|
104
|
-
assert window_of(opened) == ({"reason": "edit
|
|
102
|
+
assert window_of(opened) == ({"reason": "message-edit"}, staged)
|
|
105
103
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
106
104
|
rerun = await script.next_call()
|
|
107
|
-
assert rerun.ctx.trigger == "edit
|
|
105
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
108
106
|
assert rerun.ctx.rollback_to == "p0"
|
|
109
|
-
await drv.wait(lambda s: (s["runs"][0].get("dispatching") or {}).get("trigger") == "edit
|
|
107
|
+
await drv.wait(lambda s: (s["runs"][0].get("dispatching") or {}).get("trigger") == "message-edit")
|
|
110
108
|
trail = [
|
|
111
109
|
(window_of(state), (state["runs"] or [{}])[0].get("dispatching"))
|
|
112
110
|
for _, state in states(drv)
|
|
@@ -114,11 +112,11 @@ async def test_mid_run_edit_stages_the_window_and_promotes_in_one_envelope():
|
|
|
114
112
|
promoted = next(
|
|
115
113
|
i
|
|
116
114
|
for i, (_, record) in enumerate(trail)
|
|
117
|
-
if record is not None and record["trigger"] == "edit
|
|
115
|
+
if record is not None and record["trigger"] == "message-edit"
|
|
118
116
|
)
|
|
119
117
|
assert trail[promoted][0] == (None, None)
|
|
120
118
|
assert trail[promoted][1] == staged
|
|
121
|
-
assert trail[promoted - 1][0] == ({"reason": "edit
|
|
119
|
+
assert trail[promoted - 1][0] == ({"reason": "message-edit"}, staged)
|
|
122
120
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
123
121
|
rerun.ack()
|
|
124
122
|
rerun.finish(RunManager.Complete())
|
|
@@ -134,16 +132,16 @@ async def test_mid_run_reload_stages_reason_and_empty_messages():
|
|
|
134
132
|
call = await start_run(drv, script)
|
|
135
133
|
seq = drv.post("run/reload", reload_params("a1", anchor="m1", meta={"retry": 1}))
|
|
136
134
|
await drv.wait(lambda s: "stopping" in (s["runs"] or [{}])[0])
|
|
137
|
-
assert drv.run["stopping"] == {"reason": "reload
|
|
135
|
+
assert drv.run["stopping"] == {"reason": "message-reload"}
|
|
138
136
|
assert drv.run["nextDispatch"] == {
|
|
139
|
-
"trigger": "reload
|
|
137
|
+
"trigger": "message-reload",
|
|
140
138
|
"messages": [],
|
|
141
139
|
"rollbackTo": "m1",
|
|
142
140
|
"rootMeta": {"retry": 1},
|
|
143
141
|
}
|
|
144
142
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
145
143
|
rerun = await script.next_call()
|
|
146
|
-
assert rerun.ctx.trigger == "reload
|
|
144
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
147
145
|
assert rerun.ctx.meta() == {"retry": 1}
|
|
148
146
|
await drv.wait(lambda s: "stopping" not in (s["runs"] or [{}])[0])
|
|
149
147
|
assert drv.run["dispatching"]["rootMeta"] == {"retry": 1}
|
|
@@ -163,22 +161,22 @@ async def test_edit_of_dispatched_message_opens_the_window(command):
|
|
|
163
161
|
seq = drv.post(command, target(message=msg("m1", "edited")))
|
|
164
162
|
await drv.wait(lambda s: "stopping" in (s["runs"] or [{}])[0])
|
|
165
163
|
assert drv.replica["status"] == "running"
|
|
166
|
-
assert drv.run["stopping"] == {"reason": "edit
|
|
164
|
+
assert drv.run["stopping"] == {"reason": "message-edit"}
|
|
167
165
|
assert drv.run["nextDispatch"] == {
|
|
168
|
-
"trigger": "edit
|
|
166
|
+
"trigger": "message-edit",
|
|
169
167
|
"messages": [msg("m1", "edited")],
|
|
170
168
|
"rollbackTo": "p0",
|
|
171
169
|
}
|
|
172
170
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
173
171
|
rerun = await script.next_call()
|
|
174
|
-
assert rerun.ctx.trigger == "edit
|
|
172
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
175
173
|
assert rerun.ctx.rollback_to == "p0"
|
|
176
174
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
177
175
|
rerun.ack()
|
|
178
176
|
rerun.finish(RunManager.Complete())
|
|
179
177
|
|
|
180
178
|
|
|
181
|
-
async def
|
|
179
|
+
async def test_later_rewind_replaces_the_staged_dispatch():
|
|
182
180
|
script = Script()
|
|
183
181
|
async with run_host(script, capabilities=("rewind", "rewind-during-run")) as (
|
|
184
182
|
drv,
|
|
@@ -188,20 +186,20 @@ async def test_later_rewind_supersedes_the_staged_one():
|
|
|
188
186
|
first = drv.post("run/edit", edit_params("m1", msg("m2"), anchor="p0"))
|
|
189
187
|
await drv.wait(lambda s: "nextDispatch" in (s["runs"] or [{}])[0])
|
|
190
188
|
second = drv.post("run/reload", reload_params("a1", anchor="m1"))
|
|
191
|
-
|
|
189
|
+
assert (await drv.res(first))["type"] == "accepted"
|
|
192
190
|
await drv.wait(
|
|
193
|
-
lambda s: s["runs"][0]["nextDispatch"]["trigger"] == "reload
|
|
191
|
+
lambda s: s["runs"][0]["nextDispatch"]["trigger"] == "message-reload"
|
|
194
192
|
)
|
|
195
|
-
assert drv.run["stopping"] == {"reason": "reload
|
|
193
|
+
assert drv.run["stopping"] == {"reason": "message-reload"}
|
|
196
194
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
197
195
|
rerun = await script.next_call()
|
|
198
|
-
assert rerun.ctx.trigger == "reload
|
|
196
|
+
assert rerun.ctx.trigger == "message-reload"
|
|
199
197
|
assert (await drv.res(second))["type"] == "accepted"
|
|
200
198
|
rerun.ack()
|
|
201
199
|
rerun.finish(RunManager.Complete())
|
|
202
200
|
|
|
203
201
|
|
|
204
|
-
async def
|
|
202
|
+
async def test_stop_clears_a_staged_rewind():
|
|
205
203
|
script = Script()
|
|
206
204
|
async with run_host(script, capabilities=("rewind", "rewind-during-run")) as (
|
|
207
205
|
drv,
|
|
@@ -210,12 +208,12 @@ async def test_stop_supersedes_a_staged_rewind():
|
|
|
210
208
|
call = await start_run(drv, script)
|
|
211
209
|
seq = drv.post("run/edit", edit_params("m1", msg("m2"), anchor="p0"))
|
|
212
210
|
await drv.wait(lambda s: "nextDispatch" in (s["runs"] or [{}])[0])
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
assert (await drv.res(seq))["type"] == "accepted"
|
|
212
|
+
settled = await drv.stop()
|
|
213
|
+
assert settled["type"] == "accepted"
|
|
215
214
|
await drv.wait(lambda s: (s["runs"] or [{}])[0].get("stopping") == {"reason": "stop"})
|
|
216
215
|
assert "nextDispatch" not in drv.run
|
|
217
216
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
218
|
-
assert (await drv.res(pending["seq"]))["type"] == "accepted"
|
|
219
217
|
await drv.wait_status("stopped")
|
|
220
218
|
script.no_call()
|
|
221
219
|
|
|
@@ -235,7 +233,7 @@ async def test_sends_during_the_window_park_in_their_lanes():
|
|
|
235
233
|
assert queue_ids(drv.replica, "steerQueue") == ["s1"]
|
|
236
234
|
call.finish(RunManager.Stop(dispatch_queue=False))
|
|
237
235
|
rerun = await script.next_call()
|
|
238
|
-
assert rerun.ctx.trigger == "edit
|
|
236
|
+
assert rerun.ctx.trigger == "message-edit"
|
|
239
237
|
assert (await drv.res(seq))["type"] == "accepted"
|
|
240
238
|
assert queue_ids(drv.replica, "queue") == ["q1"]
|
|
241
239
|
assert queue_ids(drv.replica, "steerQueue") == ["s1"]
|
|
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
|