You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Nach erfolgreichem physischen Druck via POST /api/print/{slug}/batch zeigt die Hangar Result-Page den Job dauerhaft als "ausstehend". GET /api/jobs/{id} und GET /api/batches/{id} geben 404 Not Found zurück. GET /api/jobs?limit=5 liefert [].
Tatsächlich vorgefunden in der Hub-SQLite-DB:
sqlite> SELECT COUNT(*) FROM jobs; -- 0
sqlite> SELECT COUNT(*) FROM print_batches; -- 2 (beide eben gedruckt)
Die print_batches Rows referenzieren job_ids (UUID-Array), aber diese UUIDs existieren nirgendwo in der jobs Tabelle. Druck war physisch erfolgreich (Etikett aus PT-P750W). Inkonsistenz zwischen Batch-Storage und Job-Storage.
Ursache
app/services/print_queue.py:248 (und :283 in submit_paused, :367 in _resubmit_paused):
Jobs werden ausschliesslich in-memory im _jobs dict des PrintQueue Singletons gehalten. Es gibt keinsession.add(job) und keinawait session.commit(). Die SQLite-Tabelle jobs (Spalten: id, printer_id, template_key, state, payload, result, error, created_at, updated_at, started_at, finished_at, api_key_id, source_ip) bleibt leer.
Folgen:
GET /api/jobs/{id} returnt 404 — der HTTP-Handler liest aus DB, nicht aus _jobs dict
SSE-State-Replay nicht moeglich — wenn der Client sich VERSPAETET mit dem Event-Stream verbindet (z.B. weil Hangar's Page geladen wurde nachdem der Druck schon fertig war), gibt es keinen DB-Stand zum nachholen → UI bleibt auf initialem "ausstehend"
Audit-Trail unmoeglich — wer hat wann gedruckt, mit welchem Template, welcher Status?
Beim State-Transition (JobStateMachine.transition) ebenfalls session.commit() damit der aktuelle State auch nach Restart noch konsistent ist.
Phase 2.2: Worker liest aus DB (statt nur in-memory)
Beim Hub-Restart sollte der Worker queued-Jobs aus der DB lesen und ihren Pickup-State (QUEUED vs. PAUSED vs. PRINTING) sauber wiederherstellen. Faengt der Worker zwischen "ausgegeben aber nicht persistiert" Zustand ab.
Phase 2.3: Event-Replay fuer SSE
Wenn ein Client sich mit /sse/batches/{batch_id} verbindet, sollte der Hub zuerst den aktuellen Stand aus der DB ausliefern (job.state aller jobs aus der Batch), bevor er live Events anfaengt zu streamen. Damit kommt der Hangar-Result-Page auch nach Verspaetung der richtige Stand an.
Akzeptanzkriterien
Nach POST /api/print/{slug}/batch mit Status 202: SELECT COUNT(*) FROM jobs >= 1 (statt 0)
GET /api/jobs/{id} returnt korrekten Job mit aktuellem State (statt 404)
Nach Druck-Completion: state = COMPLETED in der DB
Hub-Restart wiederholt nicht erfolgreich gedruckte Jobs (Worker erkennt COMPLETED-State)
Hangar-Result-Page zeigt korrekt completed/error State auch wenn Page nach dem Druck geladen wird
TDD-Tests fuer alle drei Phasen (job persistence, worker-restart-recovery, SSE-replay)
Workaround in der Zwischenzeit
Hangar's Result-Page anzeigen, dass "Druck angestossen" reicht — keine State-Updates erwarten. SMOKE-001/SMOKE-002 sind beide physisch erfolgreich, das eigentliche Feature funktioniert. Diese Issue blockiert nur das UI-Feedback fuer Multi-Item-Batches und State-Visibility, nicht den Druck selbst.
Symptom
Nach erfolgreichem physischen Druck via
POST /api/print/{slug}/batchzeigt die Hangar Result-Page den Job dauerhaft als "ausstehend".GET /api/jobs/{id}undGET /api/batches/{id}geben 404 Not Found zurück.GET /api/jobs?limit=5liefert[].Tatsächlich vorgefunden in der Hub-SQLite-DB:
Die
print_batchesRows referenzierenjob_ids(UUID-Array), aber diese UUIDs existieren nirgendwo in derjobsTabelle. Druck war physisch erfolgreich (Etikett aus PT-P750W). Inkonsistenz zwischen Batch-Storage und Job-Storage.Ursache
app/services/print_queue.py:248(und :283 insubmit_paused, :367 in_resubmit_paused):Jobs werden ausschliesslich in-memory im
_jobsdict desPrintQueueSingletons gehalten. Es gibt keinsession.add(job)und keinawait session.commit(). Die SQLite-Tabellejobs(Spalten:id, printer_id, template_key, state, payload, result, error, created_at, updated_at, started_at, finished_at, api_key_id, source_ip) bleibt leer.Folgen:
GET /api/jobs/{id}returnt 404 — der HTTP-Handler liest aus DB, nicht aus_jobsdictReproduktion
Loesungsweg (Vorschlag)
Phase 2.1: Jobs in DB persistieren
In
submit(),submit_paused(),_resubmit_paused():Beim State-Transition (
JobStateMachine.transition) ebenfallssession.commit()damit der aktuelle State auch nach Restart noch konsistent ist.Phase 2.2: Worker liest aus DB (statt nur in-memory)
Beim Hub-Restart sollte der Worker queued-Jobs aus der DB lesen und ihren Pickup-State (
QUEUEDvs.PAUSEDvs.PRINTING) sauber wiederherstellen. Faengt der Worker zwischen "ausgegeben aber nicht persistiert" Zustand ab.Phase 2.3: Event-Replay fuer SSE
Wenn ein Client sich mit
/sse/batches/{batch_id}verbindet, sollte der Hub zuerst den aktuellen Stand aus der DB ausliefern (job.statealler jobs aus der Batch), bevor er live Events anfaengt zu streamen. Damit kommt der Hangar-Result-Page auch nach Verspaetung der richtige Stand an.Akzeptanzkriterien
POST /api/print/{slug}/batchmit Status 202:SELECT COUNT(*) FROM jobs>= 1 (statt 0)GET /api/jobs/{id}returnt korrekten Job mit aktuellem State (statt 404)state = COMPLETEDin der DBCOMPLETED-State)completed/errorState auch wenn Page nach dem Druck geladen wirdWorkaround in der Zwischenzeit
Hangar's Result-Page anzeigen, dass "Druck angestossen" reicht — keine State-Updates erwarten. SMOKE-001/SMOKE-002 sind beide physisch erfolgreich, das eigentliche Feature funktioniert. Diese Issue blockiert nur das UI-Feedback fuer Multi-Item-Batches und State-Visibility, nicht den Druck selbst.
Referenzen
docs/superpowers/specs/2026-05-30-hub-batch-endpoint-design.mdapp/models/job.py(Job table existiert, wird nur nicht geschrieben)Refs #88