From fdf5141917710267419b63bde6d7a1a4392d5654 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sat, 19 Sep 2026 18:31:49 -0400 Subject: [PATCH] Wait for the terminal lifecycle record before reading the cancelled run The detached cancel test waited for the run's status to read `failed` and then asserted on the stored `run.lifecycle` record. The projection concludes the run from Petri's `run.finished` coordinator record, and the worker stores the platform's terminal lifecycle record a moment later, so the read raced the write and the assertion failed about once in thirty runs. Wait for the record itself, and print the stored events and the run state when the assertion fails. Co-Authored-By: Claude Fable 5.1 --- lib/apps/fabro-cli/tests/it/cmd/runner.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/apps/fabro-cli/tests/it/cmd/runner.rs b/lib/apps/fabro-cli/tests/it/cmd/runner.rs index e05d39fbe..d47a9a1f9 100644 --- a/lib/apps/fabro-cli/tests/it/cmd/runner.rs +++ b/lib/apps/fabro-cli/tests/it/cmd/runner.rs @@ -20,8 +20,8 @@ use httpmock::MockServer; use super::support::{ command_log_text, created_run_id, find_run_dir, local_dev_token, output_stderr, run_state, - run_stream_items, server_endpoint, server_target, wait_for_lifecycle, wait_for_status, - write_gated_workflow, + run_stream_items, server_endpoint, server_target, wait_for_lifecycle, wait_for_run_finished, + wait_for_status, write_gated_workflow, }; use crate::support::{issue_test_worker_jwt, seed_dev_token_auth, unique_run_id}; @@ -849,12 +849,22 @@ fn detached_run_cancel_reaches_worker_over_control_websocket() { .await; }); - wait_for_status(&run_dir, &["failed"]); + // The projection concludes the run from Petri's `run.finished` record + // before the worker stores the platform's terminal `run.lifecycle` + // record, so wait for that record rather than for the status. + wait_for_run_finished(&run_dir); let events = stored_worker_events(&run_dir); assert!( events .iter() - .any(|item| is_lifecycle(item, "failed", "cancelled")) + .any(|item| is_lifecycle(item, "failed", "cancelled")), + "no failed/cancelled lifecycle record\nstored events:\n{}\nrun state:\n{}", + events + .iter() + .map(|item| serde_json::to_string(&item.item).unwrap_or_default()) + .collect::>() + .join("\n"), + serde_json::to_string_pretty(&run_state(&run_dir)).unwrap_or_default() ); }