From b423283ec3d05d4bc35cfd5b2827e77993b27174 Mon Sep 17 00:00:00 2001 From: maziggy Date: Thu, 12 Feb 2026 12:04:41 +0100 Subject: [PATCH] Fix queued jobs incorrectly skipped after duplicate execution detection (#341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the same file was queued multiple times from the archive, all jobs after the first were automatically skipped with "already printed X hours ago". The scheduler's 4-hour safety check compared the shared archive's completed_at timestamp, incorrectly treating legitimate repeat prints as phantom reprints from crash recovery. This also affected single queue items created from recently completed archives. Remove the check entirely — the crash scenario it guarded against is already prevented by committing item.status="printing" before sending the print command. --- CHANGELOG.md | 1 + backend/app/services/print_scheduler.py | 23 +---------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2835c4c31..33264c9b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to Bambuddy will be documented in this file. - **File Downloads Show Generic Filenames** ([#334](https://github.com/maziggy/bambuddy/issues/334)) — Downloaded files with special characters in their names (spaces, umlauts, parentheses) were saved as generic `file_1`, `file_2` instead of the original filename. The `Content-Disposition` header parser now handles RFC 5987 percent-encoded filenames (`filename*=utf-8''...`) used by FastAPI for non-ASCII characters. Fix applied to all download endpoints (library files, archives, source files, F3D files, project exports, support bundles, printer files). - **Printer Card Cover Image Not Updating Between Prints** — The cover image on the printer card only refreshed on page reload. The `` URL was always the same (`/printers/{id}/cover`) regardless of which print was active, so the browser served its cached image. Now appends the print name as a cache-busting query parameter so the browser fetches the new cover when a different print starts. - **Telegram Bold Title Broken by Underscores in Message** ([#332](https://github.com/maziggy/bambuddy/issues/332)) — Telegram notifications showed literal `*Title*` asterisks instead of bold text when the message body contained underscores (e.g. job name `A1_plate_8`, error code `0300_0001`). The code was disabling Markdown parsing entirely when underscores were detected. Now escapes underscores in the body with `\_` so Markdown rendering stays enabled. +- **Queued Jobs Incorrectly Archived After Duplicate Execution Detection** ([#341](https://github.com/maziggy/bambuddy/issues/341)) — When the same file was added to the print queue multiple times, only the first job executed. All subsequent jobs were automatically skipped with "already printed X hours ago" because they shared the same archive reference, and a safety check incorrectly treated them as phantom reprints. The same issue also affected single queue items created from recently completed archives. Removed the overly broad 4-hour duplicate detection check — the crash recovery scenario it guarded against is already handled by the queue item status lifecycle. ### New Features - **External Links: Open in New Tab** ([#338](https://github.com/maziggy/bambuddy/issues/338)) — External sidebar links can now optionally open in a new browser tab instead of an iframe. Sites behind reverse proxies (Traefik, nginx) that send `X-Frame-Options: SAMEORIGIN` or CSP `frame-ancestors` headers block iframe embedding, causing "refused to connect" errors. A new "Open in new tab" toggle in the add/edit link modal lets users choose per-link. Keyboard shortcuts (number keys) also respect the setting. Defaults to iframe (existing behavior) for backward compatibility. diff --git a/backend/app/services/print_scheduler.py b/backend/app/services/print_scheduler.py index 045178765..edc60c7e4 100644 --- a/backend/app/services/print_scheduler.py +++ b/backend/app/services/print_scheduler.py @@ -4,7 +4,7 @@ import asyncio import json import logging import zipfile -from datetime import datetime, timedelta +from datetime import datetime from pathlib import Path import defusedxml.ElementTree as ET @@ -862,27 +862,6 @@ class PrintScheduler: await self._power_off_if_needed(db, item) return - # Safety: Check if this archive was printed recently (within 4 hours) - # This prevents phantom reprints if a queue item got stuck in "pending" - # after its print already started due to a crash/restart - if archive.status == "completed" and archive.completed_at: - completed_at = ( - archive.completed_at.replace(tzinfo=None) if archive.completed_at.tzinfo else archive.completed_at - ) - time_since_completed = datetime.utcnow() - completed_at - if time_since_completed < timedelta(hours=4): - logger.warning( - f"Queue item {item.id}: Archive {item.archive_id} was already printed " - f"{time_since_completed.total_seconds() / 3600:.1f} hours ago, skipping to prevent duplicate" - ) - item.status = "skipped" - item.error_message = ( - f"Archive was already printed {time_since_completed.total_seconds() / 3600:.1f} hours ago" - ) - item.completed_at = datetime.utcnow() - await db.commit() - return - file_path = settings.base_dir / archive.file_path filename = archive.filename