From acd2aa825e311a19af66723e28eb93d44f905a15 Mon Sep 17 00:00:00 2001 From: maziggy Date: Tue, 10 Feb 2026 10:13:11 +0100 Subject: [PATCH] Fix wrong thumbnail when reprinting same project name (#314) The cover image cache was keyed by subtask_name and never invalidated between prints. When a user printed the same project name twice with a different bed layout, the cached thumbnail from the first print was returned instead of fetching the new one from the printer. Clear the cover cache for the printer on every print start so the next cover request downloads a fresh 3MF and extracts the current thumbnail. --- CHANGELOG.md | 1 + backend/app/api/routes/printers.py | 7 ++++++- backend/app/main.py | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 720f1dad4..de936b9a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ All notable changes to Bambuddy will be documented in this file. - **Sidebar Links Custom Icons Have Inverted Colors** ([#308](https://github.com/maziggy/bambuddy/issues/308)) — Custom uploaded icons in sidebar links had their colors inverted in dark mode due to a CSS `invert()` filter. The filter was intended for monochrome preset icons but was incorrectly applied to user-uploaded images (e.g., full-color logos). Removed the invert filter from custom icon rendering in the sidebar and the add/edit link modal. - **Virtual Printer FTP Transfer Fails With Connection Reset** ([#58](https://github.com/maziggy/bambuddy/issues/58)) — Large 3MF uploads to the virtual printer intermittently failed with `[Errno 104] Connection reset by peer` while the small verify_job always succeeded. The `_handle_data_connection` callback returned immediately, allowing the asyncio server-handler task to complete while the data connection was still in active use. The passive port listener also stayed open during transfers, risking duplicate data connections. Fixed by keeping the callback alive until the transfer completes (`_transfer_done` event), closing the passive listener after accepting the connection, and rejecting duplicate data connections. Also added a 5-second drain timeout to MQTT status pushes to prevent blocking when the slicer is busy uploading. - **Virtual Printer IP Override for Server Mode** ([#52](https://github.com/maziggy/bambuddy/issues/52)) — The `remote_interface_ip` setting (network interface override) was only used in proxy mode, but users with multiple network interfaces (LAN + Tailscale, Docker bridges) also needed it in server modes (immediate/review/print_queue). Auto-detected IP from `_get_local_ip()` followed the OS default route, causing wrong IP in TLS certificate SAN (handshake failures) and SSDP broadcasts (slicer can't discover printer). Now the interface override applies to all modes: included in certificate SAN, passed to SSDP server as advertise IP, and triggers service restart on change. UI dropdown shown for all modes when enabled (not just proxy). +- **Wrong Thumbnail When Reprinting Same Project** ([#314](https://github.com/maziggy/bambuddy/issues/314)) — Reprinting a project with the same name but a different bed layout showed the old thumbnail during printing. The cover image cache was keyed by `subtask_name` and never invalidated between prints, so a cache hit returned the stale first-print thumbnail. Now the cover cache is cleared on every print start. - **Camera Stop 401 When Auth Enabled** — Camera stop requests (`sendBeacon`) failed with 401 Unauthorized when authentication was enabled because `sendBeacon` cannot send auth headers. Replaced with `fetch` + `keepalive: true` which supports Authorization headers while remaining reliable during page unload. - **Spoolman Creates Duplicate Spools on Startup** ([#295](https://github.com/maziggy/bambuddy/pull/295)) — Each AMS tray independently fetched all spools from Spoolman, causing redundant API calls and duplicate spool creation with large databases (300+ spools). Now fetches spools once and reuses cached data across all tray operations. Added retry logic (3 attempts, 500ms delay) with connection recreation for transient network errors. - **Filament Usage Charts Inflated by Quantity Multiplier** ([#229](https://github.com/maziggy/bambuddy/issues/229)) — Daily, weekly, and filament-type charts were multiplying `filament_used_grams` by print quantity, even though the value already represents the total for the entire job. A 26-object print using 126g was counted as 3,276g. Removed the erroneous multiplier from three aggregations in `FilamentTrends.tsx`. diff --git a/backend/app/api/routes/printers.py b/backend/app/api/routes/printers.py index 311c00c9d..f113ce323 100644 --- a/backend/app/api/routes/printers.py +++ b/backend/app/api/routes/printers.py @@ -553,10 +553,15 @@ async def test_printer_connection( return result -# Cache for cover images (printer_id -> {(gcode_file, view) -> image_bytes}) +# Cache for cover images (printer_id -> {(subtask_name, plate_num, view) -> image_bytes}) _cover_cache: dict[int, dict[tuple[str, str], bytes]] = {} +def clear_cover_cache(printer_id: int) -> None: + """Clear cached cover images for a printer. Call on print start to avoid stale thumbnails.""" + _cover_cache.pop(printer_id, None) + + @router.get("/{printer_id}/cover") async def get_printer_cover( printer_id: int, diff --git a/backend/app/main.py b/backend/app/main.py index 1dc3ab073..611886a17 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -728,6 +728,11 @@ async def on_print_start(printer_id: int, data: dict): logger.info("[CALLBACK] on_print_start called for printer %s, data keys: %s", printer_id, list(data.keys())) + # Clear cached cover images so the new print's thumbnail is fetched fresh + from backend.app.api.routes.printers import clear_cover_cache + + clear_cover_cache(printer_id) + await ws_manager.send_print_start(printer_id, data) # MQTT relay - publish print start