Files
bambuddy/backend/app
maziggy c9061c2b72 fix(scheduler): cancel during queue dispatch actually cancels (#1853)
Symptom: user queued a batch of 10 prints, pressed Cancel on a pending
    row, the print started anyway. Repeated consecutively. Support bundle
    also showed 15x "sqlite3.OperationalError: database is locked" from the
    sensor history recorder in the same 8-minute window.

    Root cause is a check-then-act race in _start_print. check_queue takes
    a snapshot of pending items, then _start_print does FTP delete + FTP
    upload (5-30s) before the unconditional item.status = "printing";
    db.commit() at line 2792. /cancel commits status='cancelled' in a
    separate session during that window; the scheduler's stale in-memory
    write overwrites it and start_print ships. The lock-contention finding
    is the same shape from a different angle: _start_print did
    await db.flush() at line 2555 (after item.archive_id set + library_file
    delete) which opens the SQLite WAL writer lock and holds it through
    the FTP upload, queueing every concurrent writer behind it including
    the user's own cancel commit.

    Three guards layered:

    1) Atomic CAS at the pending->printing transition. UPDATE print_queue
       SET status='printing', started_at=NOW() WHERE id=:id AND
       status='pending'. rowcount==0 means user won; log abort, best-effort
       delete_file_async the file we just FTP'd up so it doesn't leak into
       the printer's BambuStudio file picker, send queue_item_failed WS
       event with reason="cancelled_mid_dispatch", return without calling
       printer_manager.start_print.

    2) Early db.refresh(item) + bail right after the printer connectivity
       check. Saves the wasted FTP upload when the row was already
       cancelled before _start_print resumed. Defense in depth; guard 1
       catches the same case at the CAS point.

    3) flush -> commit before the FTP block. The library-file-to-archive
       promotion's writes commit cleanly, WAL writer lock releases, sensor
       history and concurrent cancels stop queueing behind the scheduler.
       The flush-not-commit pattern was rolling back a pointer to an
       already-committed archive row, so the new behaviour matches reality
       (archive committed, pointer committed, FTP unblocked).
2026-07-07 10:53:39 +02:00
..
2026-06-26 14:40:25 +02:00
…