Files
bambuddy/backend
maziggy 1f88b9846f fix(queue): tell a pinned queue item why it is waiting (issue #3074)
A job queued as "Any X1C" explains itself when it cannot start: the
    model-based branch builds a reason for every candidate printer and puts it
    on the row, so the queue shows "Busy: X1C-01" or "Waiting for filament:
    X1C-02 (needs PETG)". The same job pinned to one printer showed nothing.
    It sat at Pending with waiting_reason NULL for as long as that printer was
    busy, which from the outside is indistinguishable from a queue that has
    stopped working -- the reporter watched fourteen minutes of it while his
    X1C ran a print he had started from its own screen.

    The fixed-printer branch had six ways out and none of them wrote the field.
    The sensor interlock (#1148) was its only writer, and it cleared the field
    up front on every pass where no sensor was holding the printer, so NULL was
    not an oversight on those paths but a guarantee.

    Every exit now writes, through one helper. The reasons reuse the
    model-based branch's vocabulary so _is_busy_only() keeps deciding what is
    worth a notification: a printer that is printing, drying, or working
    through the item ahead of this one reads as "Busy: <printer>" and stays
    silent, because it resolves itself. A printer that is off with no Auto On
    plug, and one whose plug could not switch it on, are worth saying.

    A finished plate nobody has acknowledged is split out from plain busy and
    named as itself. _is_printer_idle() returns the same plain False for that
    and for a running print, but they are not the same thing to the person
    looking at the queue: one clears itself and the other needs somebody to
    walk over to the printer.

    That notification fires on the transition into asking, where a busy-only
    reason counts as not asking. Testing whether the item was waiting at all --
    which is what the model-based branch does -- would never fire it here:
    nobody's queue goes straight from idle to an unconfirmed plate, it waits
    behind the print first. The cost is that a printer dropping offline,
    returning busy and dropping again asks twice rather than once.

    The interlock stays silent. It has never sent this notification, and a
    change about what the queue displays is not the place to start.

    Clearing the field up front is gone with it. It existed so a shut door
    could not leave "Waiting on Enclosure Door" standing while the printer
    stayed busy with something else, and the new rule carries that guarantee
    instead -- whichever exit runs next overwrites it, and the dispatch path
    clears it.

    Two paths clear it that the report did not mention. A staged item and a
    future-scheduled one skip before this branch and never reach it again, so
    anything written on an earlier pass would outlive its condition for the
    life of the row. That includes the filament-deficit check, which stages the
    item itself.

    The notification is wrapped: a queue that cannot say why it is waiting is
    the bug being fixed, and a queue that stops dispatching because a provider
    timed out would be a worse one.

    On the frontend, the queue timeline drops any pending item carrying a
    reason, on the grounds that such an item will not auto-dispatch. That held
    while only the model-based branch wrote the field; "Busy: <printer>" is
    now the commonest reason there is, and it describes the very chain the
    timeline forecasts, so the rule would have emptied the view for anyone
    whose queue is pinned. It now asks whether the reason needs the user, via
    a small shared reader of the same shape the scheduler encodes.

    Which job goes out, and when, is unchanged: running the previous scheduler
    and this one over the same 768 states dispatches the same items in the same
    order with the same statuses, across 1452 rows that now carry a reason.
2026-09-20 13:36:03 +02:00
..