fix(commands): no tumbar la recuperación de cola por un leftover de imagen huérfano - #277
Closed
cursor[bot] wants to merge 1 commit into
Closed
Conversation
A single generation.image queue row without a matching admission used to raise 503 from list/resume/discard and block every other leftover. Skip the unmatched row instead so video and valid image recovery still work. Co-authored-by: ignaciodelcano+dcl <ignaciodelcano+dcl@gmail.com>
22 tasks
25 tasks
Owner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumen ejecutivo
Qué cambia
Listar, reanudar o descartar la cola de recuperación ya no falla con 503 si un leftover
generation.imageno tiene admisión. Esa fila se omite; el resto de jobs se recuperan igual.Para qué sirve
Tras un crash, borrar el workspace de una imagen (o perder su SQLite de tareas) dejaba una fila en la cola global. Un solo mismatch bloqueaba vídeo, audio y el propio discard.
Impacto para el usuario
La recuperación de cola vuelve a listar y reanudar el trabajo válido. El leftover de imagen huérfano no se relanza; Discard lo limpia de la cola.
Riesgo
Estado
Summary
ImageGenerationCommands._recovery_taskraisedHTTPException(503, recovery_mismatch)when a durable queue row hadcapability: generation.imagebut no matchingtask_command_admissionsrow (or a driftedjob_id).GET /api/v1/jobs/recovery,POST .../resumeandPOST .../discardall callfilter_recovery/discard_recoverywith no try/except, so one stale image leftover failed the entire recovery API.Concrete trigger after #275:
_jobsis empty, soDELETE /api/v1/workspaces/{name}is allowed..maestro-tasks-v1.sqlite3but not the global queue file.The same 503 also fired for an invalid leftover workspace name or a corrupt admission snapshot.
The matcher now withholds that one row (
False) instead of raising. Non-image leftovers still pass through. Linked interrupted image leftovers still resume/discard as before.Overview
Crash leftovers stay in
DurableGenerationQueue. Recovery endpoints restore interrupted admissions, then filter the queue. Image rows must still match their admission before they are listed or resumed. Unlinked image rows are skipped so they cannot poison the batch. Native discard still removes inactive queue rows, including the orphan.Detailed changes
Backend
app/services/image_generation_commands.py:_recovery_taskreturnsNone(not an image command),(registry, task)(linked), orFalse(unlinked / invalid / storage error).filter_recoveryskipsFalse.discard_recoveryonly updates linked interrupted tasks.UI and Wizard
Unchanged.
Data, provenance and compatibility
No receipt or admission schema change. A leftover without admission is no longer recoverable as a generation job; it remains fail-closed for that row only.
Files and ownership
app/services/image_generation_commands.py— recovery matchertests/test_image_generation_commands.py— orphan + invalid workspace + job-id drift mixed with a video leftoverIntentionally untouched: queue storage, admission writes, HTTP/MCP submit, UI Generate.
Validation
Date (UTC): 2026-09-09
Base SHA: cc0d760 (
feat/shared-generation-commands)Head SHA: d057b46
Validation scope: focused
python scripts/verify_clean_repo.pypython -m compileall -q app/services/image_generation_commands.py→ cleanFocused Python tests:
.venv/bin/python -m pytest tests/test_image_generation_commands.py -q→ 25 passed, 0 failedcd ui && npm run i18n:checkUI tests: N/A (backend recovery only)
cd ui && npm run lint -- --max-warnings=0cd ui && npm run buildgit diff --check(clean commit)E2E/smoke: N/A — no browser or GPU path; matcher is covered by the focused suite
Code quality
main: pending CICI and review
CI of this HEAD: pending
Independent agent review of this HEAD: pending
Human merge click (operational, not code review): pending
Pending
Coste de la tarea
Notes and limitations
An orphaned image leftover is not reconstructed from the queue row. Resume will not start it. Discard still clears the queue file. Merge into #275 before that branch lands, or cherry-pick onto
developmentafter #275.Follow-up work
Workspace delete still does not sweep the global generation queue; that is a separate cleanup. #276 (form leftovers blocking Generate) remains open.
Checklist