fix(vp): broadcast archive_created so Archives page refreshes live (#1282)

Real-printer prints broadcast archive_created from the MQTT print_start
  handler, which the Archives page listens for to invalidate its query
  cache. The VP file-receive paths created the archive in the DB but
  never emitted the event, so the new card only appeared after a tab
  switch triggered refetch-on-focus.

  Added a small _broadcast_archive_created helper on VirtualPrinterInstance
  and called it from _archive_file (immediate mode) and _add_to_print_queue
  (queue mode). Review mode is unaffected — it creates a PendingUpload,
  not a PrintArchive. Broadcast errors are swallowed at debug level so a
  transient WebSocket issue can't break the file-receive flow.
This commit is contained in:
maziggy
2026-05-12 13:36:32 +02:00
parent 2b747e96c9
commit 0c92a4d326
3 changed files with 149 additions and 0 deletions
@@ -269,6 +269,7 @@ class VirtualPrinterInstance:
)
if archive:
logger.info("[VP %s] Archived: %s - %s", self.name, archive.id, archive.print_name)
await self._broadcast_archive_created(archive)
try:
file_path.unlink()
except OSError:
@@ -437,6 +438,7 @@ class VirtualPrinterInstance:
db.add(queue_item)
await db.commit()
logger.info("[VP %s] Added to queue: %s", self.name, queue_item.id)
await self._broadcast_archive_created(archive)
try:
file_path.unlink()
except OSError:
@@ -447,6 +449,28 @@ class VirtualPrinterInstance:
except Exception as e:
logger.error("Error adding to print queue: %s", e)
async def _broadcast_archive_created(self, archive) -> None:
"""Notify connected clients that a new archive exists.
Real-printer prints get this from main.py's MQTT print_start handler;
VP-uploaded prints need their own broadcast or the Archives page stays
stale until the user switches tabs (#1282).
"""
try:
from backend.app.core.websocket import ws_manager
await ws_manager.send_archive_created(
{
"id": archive.id,
"printer_id": archive.printer_id,
"filename": archive.filename,
"print_name": archive.print_name,
"status": archive.status,
}
)
except Exception as e:
logger.debug("[VP %s] archive_created broadcast failed: %s", self.name, e)
@staticmethod
def _extract_plate_id(file_path: Path) -> int | None:
"""Extract plate index from 3MF slice_info.config."""