feat: require two recent failures to queue a season
The season branch of the attention queue listed a season on one failed grab of any age, so `GET /api/queues/attention` returned Rick and Morty with every season it has and buried the one that needed attention. Two changes, both stated in DESIGN.md §5.7: - The season branch now enforces the same bar the episode branch does: two grabs that hard-failed on *different* releases. - A failed grab counts toward the queue for 30 days (`arr_db::ATTENTION_WINDOW`). Nothing clears a `grabs` row, so without a window the queue only grows and can never be emptied. #181 gave the pack guard a backoff curve for the same reason; this is the queue's version of §6.2's "it never gives up entirely, it goes quiet". A season the operator dealt with stops failing and drops out; one still breaking keeps failing (the pack guard retries at worst weekly) and stays. The window applies to all three hard-fail lanes — movie, episode and season — because DESIGN.md states one rule for the queue, and to the daemon's needs-a-decision notifier as well as the API, since both read the same queue and a season-per-failure notification is the same noise on a different channel. No schema change: `grabs.grabbed_at` already carries the timestamp. Gate: `just ci` green (486 tests).
This commit is contained in:
@@ -17,6 +17,15 @@ use sqlx::{migrate::MigrateError, SqlitePool};
|
||||
/// The migrations embedded in the binary, so a deploy is one file.
|
||||
pub static MIGRATOR: sqlx::migrate::Migrator = sqlx::migrate!("./migrations");
|
||||
|
||||
/// §5.7: how long a failed grab keeps counting toward the needs-a-decision
|
||||
/// queue, as a SQLite time modifier.
|
||||
///
|
||||
/// Nothing ever clears a `grabs` row, so without a bound the queue only grows
|
||||
/// and the one season that wants attention sits behind the ones that do not.
|
||||
/// Callers pair it with the `grabbed_at` format:
|
||||
/// `strftime('%Y-%m-%dT%H:%M:%fZ', 'now', ATTENTION_WINDOW)`.
|
||||
pub const ATTENTION_WINDOW: &str = "-30 days";
|
||||
|
||||
/// How long a writer waits for the write lock before giving up.
|
||||
const BUSY_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user