Преглед изворни кода

Improved duplicate archive check

maziggy пре 4 месеци
родитељ
комит
b0c576c8a8
1 измењених фајлова са 41 додато и 25 уклоњено
  1. 41 25
      backend/app/main.py

+ 41 - 25
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 = []