research: rerun cancels orphan runs first so 409 doesn't block restart
The previous rerun guard (standby OR (processing AND in_flight==0)) still 409'd when a lingering queued/running row existed — typically an orphan from a server restart mid-pipeline, before the reaper or stale-checkpoint requeuer had marked it failed. Now: allow rerun on any 'processing' topic; before enqueuing the fresh run, batch-cancel every in-flight run for the topic so the new run isn't racing them. Terminal states (reviewing / publishing / published) still 409 as before.
This commit is contained in:
@@ -679,16 +679,26 @@ pub async fn start_topic(
|
||||
.await?
|
||||
.ok_or(ApiError::NotFound)?;
|
||||
// Allow the fresh-start path (standby) AND the rerun path (topic
|
||||
// parked in `processing` after all runs failed / no runs remain in
|
||||
// flight). Blocks accidental double-fires on a live pipeline
|
||||
// (in_flight > 0) and terminal states (reviewing / publishing /
|
||||
// published).
|
||||
let in_flight =
|
||||
cm_db::repo::topology_runs::active_runs_for_research_topic(&state.pool, id).await?;
|
||||
let can_start = topic.status == "standby" || (topic.status == "processing" && in_flight == 0);
|
||||
// parked in `processing`). For rerun, first cancel any lingering
|
||||
// queued/running runs (typically orphans left over from a server
|
||||
// restart mid-pipeline) so the fresh enqueue isn't racing them.
|
||||
// Terminal states (reviewing / publishing / published) still 409.
|
||||
let can_start = topic.status == "standby" || topic.status == "processing";
|
||||
if !can_start {
|
||||
return Err(ApiError::Conflict);
|
||||
}
|
||||
if topic.status == "processing" {
|
||||
let orphan_ids =
|
||||
cm_db::repo::topology_runs::active_run_ids_for_research_topic(&state.pool, id).await?;
|
||||
for run_id in orphan_ids {
|
||||
// Best-effort — cancel just marks the row; the actual worker
|
||||
// (if still alive) stops at its next step boundary. If the
|
||||
// worker is dead (server restart), the row transitions and
|
||||
// stops being counted as in-flight immediately.
|
||||
let _ =
|
||||
cm_db::repo::topology_runs::cancel(&state.pool, run_id, user.workspace_id).await;
|
||||
}
|
||||
}
|
||||
// D1 fold — refuse to double-fire when a scheduled research loop
|
||||
// already owns this topic. Otherwise clicking the legacy "Start
|
||||
// research" button while a loop iteration is in flight would spawn
|
||||
|
||||
Reference in New Issue
Block a user