refactor(daemon): extract tv queue roll-up
This commit is contained in:
@@ -147,78 +147,10 @@ impl AttentionAction {
|
||||
});
|
||||
}
|
||||
|
||||
let mut tv: HashMap<i64, (String, Option<i64>, TvEntry)> = HashMap::new();
|
||||
|
||||
let tv_no_pt_source = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
e.id AS "episode_id!: i64"
|
||||
FROM episodes e
|
||||
JOIN seasons se ON se.id = e.season_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
JOIN roots root ON root.id = s.root_id
|
||||
WHERE root.audience = 'kids'
|
||||
AND s.blocked = 0
|
||||
AND e.wanted = 1 AND e.state = 'missing' AND e.search_attempts > 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM episode_releases er
|
||||
JOIN releases r ON r.id = er.release_id
|
||||
WHERE er.episode_id = e.id AND r.verdict IN ('eligible', 'waived')
|
||||
)
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in tv_no_pt_source {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.no_pt_source
|
||||
.push(row.episode_id);
|
||||
}
|
||||
|
||||
let episode_hard_fails = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
g.target_id AS "episode_id!: i64"
|
||||
FROM grabs g
|
||||
JOIN episodes e ON g.target_kind = 'episode' AND e.id = g.target_id
|
||||
JOIN seasons se ON se.id = e.season_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
WHERE g.state = 'failed'
|
||||
GROUP BY s.id, s.title, s.year, e.id
|
||||
HAVING count(DISTINCT g.release_id) >= 2
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in episode_hard_fails {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.hard_failed_episodes
|
||||
.push(row.episode_id);
|
||||
}
|
||||
|
||||
let season_pack_fails = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
g.target_id AS "season_id!: i64"
|
||||
FROM grabs g
|
||||
JOIN seasons se ON g.target_kind = 'season' AND se.id = g.target_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
WHERE g.state = 'failed'
|
||||
GROUP BY s.id, s.title, s.year, se.id
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in season_pack_fails {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.failed_season_packs
|
||||
.push(row.season_id);
|
||||
}
|
||||
|
||||
for (&series_id, (title, year, entry)) in &tv {
|
||||
for (series_id, title, year, entry) in queue_tv(database).await? {
|
||||
queued.insert(
|
||||
Subject::Series(series_id),
|
||||
(title_with_year(title, *year), entry.reason()),
|
||||
(title_with_year(&title, year), entry.reason()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -262,18 +194,98 @@ fn title_with_year(title: &str, year: Option<i64>) -> String {
|
||||
}
|
||||
|
||||
/// The series' roll-up entry, created empty on first sight.
|
||||
fn tv_entry<'a>(
|
||||
tv: &'a mut HashMap<i64, (String, Option<i64>, TvEntry)>,
|
||||
fn tv_entry(
|
||||
tv: &mut HashMap<i64, (String, Option<i64>, TvEntry)>,
|
||||
series_id: i64,
|
||||
title: String,
|
||||
year: Option<i64>,
|
||||
) -> &'a mut TvEntry {
|
||||
) -> &mut TvEntry {
|
||||
&mut tv
|
||||
.entry(series_id)
|
||||
.or_insert_with(|| (title, year, TvEntry::default()))
|
||||
.2
|
||||
}
|
||||
|
||||
/// TV roll-up (§9.5): every queued series with what put it there — wanted
|
||||
/// episodes whose every candidate was rejected for language, episodes two
|
||||
/// different releases hard-failed post-probe, and seasons whose pack grab
|
||||
/// hard-failed. One entry per series, so the notification can be one per
|
||||
/// series however long the broken season is.
|
||||
async fn queue_tv(database: &Db) -> Result<Vec<(i64, String, Option<i64>, TvEntry)>, sqlx::Error> {
|
||||
let mut tv = HashMap::new();
|
||||
|
||||
let tv_no_pt_source = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
e.id AS "episode_id!: i64"
|
||||
FROM episodes e
|
||||
JOIN seasons se ON se.id = e.season_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
JOIN roots root ON root.id = s.root_id
|
||||
WHERE root.audience = 'kids'
|
||||
AND s.blocked = 0
|
||||
AND e.wanted = 1 AND e.state = 'missing' AND e.search_attempts > 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM episode_releases er
|
||||
JOIN releases r ON r.id = er.release_id
|
||||
WHERE er.episode_id = e.id AND r.verdict IN ('eligible', 'waived')
|
||||
)
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in tv_no_pt_source {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.no_pt_source
|
||||
.push(row.episode_id);
|
||||
}
|
||||
|
||||
let episode_hard_fails = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
g.target_id AS "episode_id!: i64"
|
||||
FROM grabs g
|
||||
JOIN episodes e ON g.target_kind = 'episode' AND e.id = g.target_id
|
||||
JOIN seasons se ON se.id = e.season_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
WHERE g.state = 'failed'
|
||||
GROUP BY s.id, s.title, s.year, e.id
|
||||
HAVING count(DISTINCT g.release_id) >= 2
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in episode_hard_fails {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.hard_failed_episodes
|
||||
.push(row.episode_id);
|
||||
}
|
||||
|
||||
let season_pack_fails = sqlx::query!(
|
||||
r#"
|
||||
SELECT s.id AS "series_id!: i64", s.title AS "title!: String", s.year,
|
||||
g.target_id AS "season_id!: i64"
|
||||
FROM grabs g
|
||||
JOIN seasons se ON g.target_kind = 'season' AND se.id = g.target_id
|
||||
JOIN series s ON s.id = se.series_id
|
||||
WHERE g.state = 'failed'
|
||||
GROUP BY s.id, s.title, s.year, se.id
|
||||
"#
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await?;
|
||||
for row in season_pack_fails {
|
||||
tv_entry(&mut tv, row.series_id, row.title, row.year)
|
||||
.failed_season_packs
|
||||
.push(row.season_id);
|
||||
}
|
||||
|
||||
Ok(tv
|
||||
.into_iter()
|
||||
.map(|(id, (t, y, e))| (id, t, y, e))
|
||||
.collect())
|
||||
}
|
||||
|
||||
impl Action for AttentionAction {
|
||||
fn name(&self) -> &'static str {
|
||||
"attention"
|
||||
@@ -359,7 +371,7 @@ mod tests {
|
||||
VALUES (?, ?, ?, 1, 'missing', 1)",
|
||||
)
|
||||
.bind(season_id)
|
||||
.bind(number as i64 + 1)
|
||||
.bind(i64::try_from(number).unwrap_or(0) + 1)
|
||||
.bind(format!("Episode {number}"))
|
||||
.execute(database.pool())
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user