Skip to content

fix(jobs): reject active output path conflicts - #219

Merged
kfstorm merged 3 commits into
mainfrom
calm-chipmunk
Oct 4, 2026
Merged

kfstorm merged 3 commits into
mainfrom
calm-chipmunk

Conversation

@kfstorm

@kfstorm kfstorm commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

Reject Job creation and retry when another non-terminal Job already targets the same relative base output path. This enforces the Jobs-layer invariant that at most one non-terminal Job may target a given logical output, including submissions with different Model Profiles, Term maps, subtitle sources, or translation options.

Jobs.create() and Jobs.retry() share a small private output-path guard. Creation checks the calculated output before creating or persisting a record. Retry checks the recalculated base output before transitioning a Failed or Interrupted Job to Queued, even if the previous attempt saved an append-numbered path. A rejected retry leaves both the terminal Job and the active Job unchanged.

The guard also recalculates each active Job's base output from its request. This keeps the logical target stable when execution updates the saved output_path to an append-numbered path such as .2.srt or .3.srt, so repeated submissions and retries still conflict with the running Job.

The guard runs while callers hold the existing lifecycle and record locks. The lifecycle lock covers the check through persistence, so concurrent submissions cannot both pass. A conflict raises output_job_active with the relative output_path and the active job_id.

Batch creation reuses this guard through create(). Conflicting items receive the existing per-item error envelope, and other valid items continue to be created.

Completed, Failed, Cancelled, and Interrupted Jobs do not block a new submission. Existing disk-file conflict policies retain their behavior, including append numbering after an earlier Job completes. Translate draft retention is unchanged.

Add focused Jobs and HTTP contract coverage for conflicting requests, changed translation options, terminal resubmission, concurrent creation, batch isolation, and creation or retry conflicts after an active Job selects an append-numbered path. Rejected retries preserve both Jobs and their persisted records. Adjust existing tests that previously queued multiple Jobs for the same output.

Reject new Jobs when a non-terminal Job already targets the same relative output path, regardless of translation options. Keep the check and record persistence under the existing lifecycle lock and expose output_job_active with the output path and active Job ID.

Reuse the guard for batch item error isolation while preserving terminal resubmission and disk output conflict policies. Cover concurrent creation and HTTP errors, and adapt existing tests that queued multiple Jobs for one output.
Share the active output-path check between creation and retry. Validate the recalculated base output before moving a terminal Job to Queued, under the existing lifecycle and record locks.

Cover Failed and Interrupted retries when another Job is translating to the base output, including a previous append-numbered attempt. Rejected retries preserve both Job details and persisted records.
Recalculate each non-terminal Job's base output in the shared guard. Append-number execution changes the saved output path, so comparing that mutable path allowed duplicate logical targets through creation and retry.

Cover creation while an active Job targets a numbered output and extend Failed and Interrupted retry coverage to the same case.
@kfstorm
kfstorm merged commit 6cc44f4 into main Oct 4, 2026
3 checks passed
@kfstorm
kfstorm deleted the calm-chipmunk branch October 4, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant