From b0c576c8a89396126badc03d7326ba6e0351f9de Mon Sep 17 00:00:00 2001 From: maziggy Date: Sun, 4 Jan 2026 16:46:59 +0100 Subject: [PATCH] Improved duplicate archive check --- backend/app/main.py | 66 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/backend/app/main.py b/backend/app/main.py index 901bedf9b..e140a08f2 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,7 +1,7 @@ import asyncio import logging from contextlib import asynccontextmanager -from datetime import datetime, timedelta +from datetime import UTC, datetime, timedelta from logging.handlers import RotatingFileHandler from fastapi import FastAPI @@ -513,30 +513,46 @@ async def on_print_start(printer_id: int, data: dict): ) existing_archive = existing.scalar_one_or_none() if existing_archive: - logger.info(f"Skipping duplicate - already have printing archive {existing_archive.id} for {check_name}") - # Track this as the active print - _active_prints[(printer_id, existing_archive.filename)] = existing_archive.id - # Also set up energy tracking if not already tracked - if existing_archive.id not in _print_energy_start: - try: - plug_result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == printer_id)) - plug = plug_result.scalar_one_or_none() - if plug: - energy = await tasmota_service.get_energy(plug) - if energy and energy.get("total") is not None: - _print_energy_start[existing_archive.id] = energy["total"] - logger.info( - f"Recorded starting energy for existing archive {existing_archive.id}: {energy['total']} kWh" - ) - except Exception as e: - logger.warning(f"Failed to record starting energy for existing archive: {e}") - # Send notification with archive data (existing archive) - if not notification_sent: - archive_data = {"print_time_seconds": existing_archive.print_time_seconds} - await _send_print_start_notification(printer_id, data, archive_data, logger) - # Extract printable objects from the archived 3MF file - _load_objects_from_archive(existing_archive, printer_id, logger) - return + # Check if archive is stale (older than 4 hours) - likely a failed/cancelled print + # that didn't get properly updated + archive_age = datetime.now(UTC) - existing_archive.created_at.replace(tzinfo=UTC) + if archive_age.total_seconds() > 4 * 60 * 60: # 4 hours + logger.warning( + f"Found stale 'printing' archive {existing_archive.id} (age: {archive_age}), " + f"marking as cancelled and creating new archive" + ) + existing_archive.status = "cancelled" + existing_archive.failure_reason = "Stale - print likely cancelled or failed without status update" + await db.commit() + # Fall through to create new archive (don't return) + existing_archive = None # Clear so we don't use stale archive + else: + logger.info( + f"Skipping duplicate - already have printing archive {existing_archive.id} for {check_name}" + ) + # Track this as the active print + _active_prints[(printer_id, existing_archive.filename)] = existing_archive.id + # Also set up energy tracking if not already tracked + if existing_archive.id not in _print_energy_start: + try: + plug_result = await db.execute(select(SmartPlug).where(SmartPlug.printer_id == printer_id)) + plug = plug_result.scalar_one_or_none() + if plug: + energy = await tasmota_service.get_energy(plug) + if energy and energy.get("total") is not None: + _print_energy_start[existing_archive.id] = energy["total"] + logger.info( + f"Recorded starting energy for existing archive {existing_archive.id}: {energy['total']} kWh" + ) + except Exception as e: + logger.warning(f"Failed to record starting energy for existing archive: {e}") + # Send notification with archive data (existing archive) + if not notification_sent: + archive_data = {"print_time_seconds": existing_archive.print_time_seconds} + await _send_print_start_notification(printer_id, data, archive_data, logger) + # Extract printable objects from the archived 3MF file + _load_objects_from_archive(existing_archive, printer_id, logger) + return # Build list of possible 3MF filenames to try possible_names = []