sched: address R2 fail-closed and fault-proof findings
This commit is contained in:
@@ -65,15 +65,26 @@ def test_manual_run_persists_admission_before_dispatch(tmp_path: Path) -> None:
|
||||
|
||||
|
||||
def test_fault_before_admission_never_dispatches(tmp_path: Path, monkeypatch) -> None:
|
||||
import wf_api.runs as runs_module
|
||||
|
||||
api, store = _api_with_echo(tmp_path / "fault-before")
|
||||
real_write = store._write_json
|
||||
dispatched: list[str] = []
|
||||
real_plan = runs_module.raw_plan_from_artifact
|
||||
|
||||
def _fail_save(admission) -> None: # type: ignore[no-untyped-def]
|
||||
raise OSError("injected admission failure")
|
||||
def _fail_on_admission(path: Path, payload: object) -> None:
|
||||
if path.name == "admission.json":
|
||||
raise OSError("injected admission failure")
|
||||
real_write(path, payload)
|
||||
|
||||
# Admission persist precedes dispatch in run_deployment ordering: a failure
|
||||
# here must propagate before any run view exists, so no dispatch could
|
||||
# have produced a stopped checkpoint.
|
||||
monkeypatch.setattr(store, "save_admission", _fail_save)
|
||||
def _spy_plan(artifact): # type: ignore[no-untyped-def]
|
||||
dispatched.append("dispatch")
|
||||
return real_plan(artifact)
|
||||
|
||||
# Real serialization fault at the admission file: nothing after it
|
||||
# (plan building, dispatch, stopped persist) may run.
|
||||
monkeypatch.setattr(store, "_write_json", _fail_on_admission)
|
||||
monkeypatch.setattr(runs_module, "raw_plan_from_artifact", _spy_plan)
|
||||
try:
|
||||
asyncio.run(
|
||||
api.run_deployment(
|
||||
@@ -84,8 +95,10 @@ def test_fault_before_admission_never_dispatches(tmp_path: Path, monkeypatch) ->
|
||||
raise AssertionError("fault must propagate")
|
||||
except OSError:
|
||||
pass
|
||||
assert store.list_admissions() == []
|
||||
assert store.list_runs() == []
|
||||
assert dispatched == []
|
||||
fresh = FileRunStore(store.root)
|
||||
assert fresh.list_admissions() == []
|
||||
assert fresh.list_runs() == []
|
||||
|
||||
|
||||
def test_captured_invocation_freezes_input(tmp_path: Path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user