Added
- Thorough health checks are now tunable for slow codecs (AV1) and large files. Three new env vars:
HEALARR_HEALTH_CHECK_THOROUGH_TIMEOUT(default10m) - raise this if scans repeatedly time out and end up parked in the rescan queue.HEALARR_HEALTH_CHECK_THOROUGH_DURATION(default0, no limit) - when set (e.g.60s), the thorough decode walks only the first N seconds via ffmpeg-t. Catches header errors, codec-init errors, decode errors at the start, and files that will not open at all; trades completeness for speed.HEALARR_HEALTH_CHECK_HWACCEL(defaultauto) - opportunistic ffmpeg hardware acceleration. Probesffmpeg -hwaccelsonce and adds-hwaccel autoif any accelerator is reported; falls back silently to software on hosts without one.offto disable,<name>(e.g.cuda,vaapi,videotoolbox) to force a specific one.
Fixed
- Cancelling a scan now actually cancels it. Previously
CancelScanonly signaled the in-memoryctx.cancel()and never persisted the new status, so /scans and Dashboard kept showing the row as "running" on reload (and the "Scan cancelled" toast was misleading). For stale "running" rows left over from a previous hard restart - where there is nothing to signal in memory - the cancel button did literally nothing (a 404 from the handler). Cancel now always writesstatus='cancelled'withcompleted_atto the DB, so both live cancels and stale-row cleanups work. The "AND completed_at IS NULL" guard prevents a benign cancel-vs-completion race from clobbering a real completion. - Stale "running" scan rows from a previous hard restart are no longer shown forever. On startup the scanner now reconciles: any row left in an active status (
running/enumerating/scanning) that this process did not start was orphaned by aSIGKILL/OOM/crash that prevented the normalMarkInterruptedshutdown path from running. Those rows are now marked cancelled at startup witherror_message='abandoned on Healarr restart'.pausedandinterruptedare left alone (legitimate resumable states). /corruptionswith the "All" filter no longer crashes with a database scan error. The notifier was publishing everyNotificationSent/NotificationFailedwith a hardcodedaggregate_type="corruption", so notifications fired for non-corruption events (e.g. a Pushover alert forSystemHealthDegraded) leaked intocorruption_summaryas stray rows withNULL file_path. Loading the corruptions page with no filter included them and tripped aconverting NULL to stringscan error. The notifier now propagates the source event's aggregate type, defaults defensively to"notification"if missing (never"corruption"), and a migration cleans up any rows already polluted while tightening thecorruption_statusview as belt-and-braces.
Full Changelog: v1.3.2...v1.3.3