Files
arr/.sqlx/query-b35fe903d45f1c3ec7a963aac599331f602ea73b2e860a623b79ae435beca614.json
T
Miguel Palhas ac0e80c044 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).
2026-08-25 10:09:07 +01:00

195 lines
4.5 KiB
JSON

{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, poster_path, vote_average, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE (SELECT count(DISTINCT g.release_id) FROM grabs g WHERE g.target_kind = 'movie' AND g.target_id = movies.id AND g.state = 'failed' AND g.grabbed_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now', ?)) >= 2 ORDER BY title",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "root_id"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "wanted"
}
}
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "overrides"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "state"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "blocked"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "poster_path",
"ordinal": 12,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 13,
"type_info": "Float",
"origin": {
"Table": {
"table": "movies",
"name": "vote_average"
}
}
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 14,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "waiver"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "b35fe903d45f1c3ec7a963aac599331f602ea73b2e860a623b79ae435beca614"
}