Skip to content

fix(translator): let a manual run lift the debounce it is waiting on - #140

Open
SearheiParkhamchuk wants to merge 1 commit into
mainfrom
fix/translator-manual-run-clears-debounce
Open

fix(translator): let a manual run lift the debounce it is waiting on#140
SearheiParkhamchuk wants to merge 1 commit into
mainfrom
fix/translator-manual-run-clears-debounce

Conversation

@SearheiParkhamchuk

Copy link
Copy Markdown
Contributor

Closes #127.

What was wrong

The panel's Run now button did nothing for a job queued with an auto-translate debounce, and then said the job was already in progress.

run() hands the job to Payload's picker, which declines a job that is processing, carries hasError, or has a waitUntil that has not elapsed. Blockers were cleared only for a job that was processing or had failed — a queued one is neither, so its waitUntil survived, the picker took nothing, and the single failure reason the runner has (already_running) went back to the editor.

Two things were wrong with that. The button did not do what it is named. And the explanation was confidently false: the job was not running, it was waiting.

The fix

One line in PayloadJobsTaskRunner.run(): clear the blockers unconditionally. A manual run means now, so it lifts the debounce along with the lock and the spent retry budget.

After this, the case where the picker still declines is one where already_running is true — another job for the same document holds the concurrency key, when the host has enabled Payload's concurrency control.

PayloadJob also gained the waitUntil field. The row always had it; the type did not, which is part of why this was invisible from the runner.

How it was verified

Test first. Against the unchanged code the new case fails with Number of calls: 0 — the blockers were never cleared. With the fix it passes, and putting the old condition back reddens it again.

One existing test asserted expect(mockPayload.update).not.toHaveBeenCalled() for a queued job — it pinned exactly the behaviour this change reverses. Rather than delete the assertion, it now checks that the clear happens before the picker is called, which is what makes lifting the debounce meaningful.

Scope note

#127 also asked for a distinct RunResult member so the admin could name the reason. That is not added here: after this change the one remaining decline genuinely is "already running", so a new member would have no case to describe. If a future decline reason appears that is neither, it should come with its own member then.

"Run now" did nothing for a job queued with an auto-translate debounce. The
picker skips a job whose `waitUntil` has not elapsed, and the blockers were
only cleared for a job that was processing or had failed — a queued one is
neither. So the button cleared nothing, the picker took nothing, and the
caller was told the job was already in progress, which it was not.

A manual run means now, so it now clears the debounce along with the lock and
the spent retry budget. The remaining reasons the picker can decline are ones
where "already running" is true: another job for the same document holds the
concurrency key.

`PayloadJob` gained the `waitUntil` field it always had in the row — part of
why this was invisible.

Closes #127
@vercel

vercel Bot commented Sep 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ideal-cms Ready Ready Preview Sep 13, 2026 11:37am UTC

Request Review

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.

translator: run() reports success even when the job was skipped

1 participant