Rolling integrity queue, time budgets, bitrot detection (v2.6.58-62)#62
Merged
Conversation
….62) Integrity checks now sweep the library as a rolling stalest-first queue (batched fetches keyed on last_integrity_check_date) instead of a single all-or-nothing full-table pass, resume after crash or cancellation by construction, and stamp every terminal outcome in bulk. file_changes schedules can carry a per-run time budget (soft deadline, drain on expiry, saturated-tier skip-ahead) so successive runs cover the library in slices. Hash mismatches are now classified: changed mtime = legitimate modification, unchanged mtime = suspected bitrot. Flagged files keep their stored baseline through every scan writer (shared apply_scan_baseline guard), jump the integrity queue, auto-expire after consecutive stable checks plus a clean rescan, and can be manually accepted via POST /api/bitrot/accept. One aggregated high-priority notification fires per run through the new NotificationRule dispatcher. Stored mtimes are written as UTC with a per-row trust flag; untrusted pre-upgrade rows re-baseline on their first check. Removes the dead serial MediaChecker.check_file_changes path and a per-run AsyncResult accumulation leak, and adds a composite index for the queue ordering.
Schedule create/update/delete dispatched reload_schedules_task via Celery, but prefork workers execute tasks in pool children while APScheduler runs only in the scheduler-lock-holding main process. The reload always landed in a child and was skipped, so schedule changes never reached the running scheduler without a container restart. The scheduler process now re-syncs its jobs from the database every 60 seconds, gated on a fingerprint of schedule definitions so jobs are only rebuilt on actual change. next_run is computed at schedule creation so the UI shows the upcoming fire before the first run.
Budgeted integrity runs sweep the library in slices, so no single run report answers whether every file has been verified. /api/stats now returns an integrity block: files checked ever and in the last 30 days, coverage percent, never-checked count, oldest check date, and current bitrot-suspected count. The dashboard gains an Integrity Checked stat card with the full breakdown in its tooltip.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
last_integrity_check_datereplace the single full-table load, every terminal outcome (success, hash error, abandoned task, unreadable result) stamps the cursor in bulk, and interrupted runs resume where they left off. In-flight, stamp-failed, and dispatch-failed rows are excluded from re-fetches so the producer always terminates.file_changesschedules accepttime_budget_minutes(NULL = unlimited): a soft deadline that stops new dispatch, drains in-flight hashes, and reports coverage. Budgeted batches dispatch largest-first with saturated-tier skip-ahead so huge files start early without capping concurrency. Manual runs stay unlimited unless the request passes a budget.modified: content change with unchanged mtime (2 s epsilon) is suspected bitrot. Flagged files keep their stored hash/mtime baseline through every scan writer (single sharedapply_scan_baselineguard, used by both the serial save path and the parallel chunk workers), jump the queue, auto-expire afterBITROT_STABLE_CHECKS_TO_EXPIREstable checks plus a clean rescan, and can be accepted manually viaPOST /api/bitrot/accept. Detection date/details are permanent.mtime_baseline_utctrust flag; pre-upgrade naive-local rows re-baseline on their first check (hash-match rows re-baseline in place, mismatch rows via rescan) so old data can never produce false bitrot alarms. Scan-cache validity now keys on content-hash equality so the UTC change cannot force a full-library re-decode.dispatch_event()joins activeNotificationRulerows to active providers;bitrot_suspectedsends one aggregated high-priority notification per run./api/scan-resultsgain bitrot fields/filter.MediaChecker.check_file_changespath and a per-runAsyncResultaccumulation leak; added a composite index matching the queue ordering.Version
2.6.58 through 2.6.62 (see CHANGELOG.MD for per-version detail).
Note for deploy: the v2.6.61 migration adds six columns and two indexes to
scan_results; the index build briefly holds the migration advisory lock at startup on large tables.Test plan
test_real_media_samples.pyon slow local hardware, present on main)