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?
|
.await?
|
||||||
.ok_or(ApiError::NotFound)?;
|
.ok_or(ApiError::NotFound)?;
|
||||||
// Allow the fresh-start path (standby) AND the rerun path (topic
|
// Allow the fresh-start path (standby) AND the rerun path (topic
|
||||||
// parked in `processing` after all runs failed / no runs remain in
|
// parked in `processing`). For rerun, first cancel any lingering
|
||||||
// flight). Blocks accidental double-fires on a live pipeline
|
// queued/running runs (typically orphans left over from a server
|
||||||
// (in_flight > 0) and terminal states (reviewing / publishing /
|
// restart mid-pipeline) so the fresh enqueue isn't racing them.
|
||||||
// published).
|
// Terminal states (reviewing / publishing / published) still 409.
|
||||||
let in_flight =
|
let can_start = topic.status == "standby" || topic.status == "processing";
|
||||||
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);
|
|
||||||
if !can_start {
|
if !can_start {
|
||||||
return Err(ApiError::Conflict);
|
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
|
// D1 fold — refuse to double-fire when a scheduled research loop
|
||||||
// already owns this topic. Otherwise clicking the legacy "Start
|
// already owns this topic. Otherwise clicking the legacy "Start
|
||||||
// research" button while a loop iteration is in flight would spawn
|
// research" button while a loop iteration is in flight would spawn
|
||||||
|
|||||||
Reference in New Issue
Block a user