From b73e91219e92622795a938ef6337dbf475375d90 Mon Sep 17 00:00:00 2001 From: Daan Meijer Date: Fri, 16 Oct 2026 15:06:13 +0200 Subject: [PATCH] The judge's unusable waits for final: next to an unread range a release's par2 or files may still come Co-Authored-By: Claude Opus 5.5 --- app/services/release_judge.ts | 4 +++- tests/functional/release_judge.spec.ts | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/services/release_judge.ts b/app/services/release_judge.ts index b7a8340..4930062 100644 --- a/app/services/release_judge.ts +++ b/app/services/release_judge.ts @@ -74,9 +74,11 @@ export const RULES: Rule[] = [ }, { name: 'unusable', - says: 'random names, no name inside, no par2 or inner-name merge, no spot, a day after settling', + says: 'random names, no name inside, no par2 or inner-name merge, no spot, a day after settling, and final', + // Final (release_final): next to an unread range its par2 or the rest of its files may still come (LOG.md 2026-10-16 (67)). sql: `SELECT r.id FROM releases r WHERE r.settled_at < now() - interval '1 day' AND NOT r.readable AND r.inner_name IS NULL + AND release_final(r.group_id, r.first_article, r.last_article, r.posted_at, r.last_posted_at) AND NOT EXISTS (SELECT 1 FROM release_merges m WHERE m.into_id = r.id) AND NOT EXISTS (SELECT 1 FROM release_spots s WHERE s.release_id = r.id) AND NOT EXISTS (SELECT 1 FROM par2_sets p WHERE p.release_id = r.id)`, diff --git a/tests/functional/release_judge.spec.ts b/tests/functional/release_judge.spec.ts index 7eb2ab4..988dc2f 100644 --- a/tests/functional/release_judge.spec.ts +++ b/tests/functional/release_judge.spec.ts @@ -3,6 +3,7 @@ import db from '@adonisjs/lucid/services/db' import testUtils from '@adonisjs/core/services/test_utils' import { ReleaseJudge } from '#services/release_judge' import SearchService from '#services/search_service' +import RangeBlocks from '#services/range_blocks' test.group('ReleaseJudge', (group) => { group.each.setup(() => testUtils.db().withGlobalTransaction()) @@ -63,9 +64,18 @@ test.group('ReleaseJudge', (group) => { const unlocked = await release('Known.Password', { passworded: true }) await db.table('release_passwords').insert({ release_id: unlocked, password: 'pw', source: 'spot-text' }) - const unusable = await release('ab12CD34ef56GH78ij90', { readable: false }) - const fresh = await release('zz12CD34ef56GH78ij90', { readable: false, settled_at: new Date() }) - const spotted = await release('yy12CD34ef56GH78ij90', { readable: false }) + // A block of done ranges around the unusable ones (release_final); one beside an unread range isn't judged yet. + await db.table('groups').insert({ id: 1, name: 'alt.binaries.judged', priority: 1 }).onConflict('id').ignore() + await db.table('ranges').multiInsert([ + { group_id: 1, start_id: 1, end_id: 1000, next_id: 1001, status: 'done', posted_low: new Date(settled.getTime() - 86400_000), posted_high: new Date(settled.getTime() + 86400_000) }, + { group_id: 1, start_id: 1001, end_id: 2000, next_id: 1001, status: 'planned' }, + ]) + await RangeBlocks.rebuild() + const placed = { first_article: 100, last_article: 110 } + const unusable = await release('ab12CD34ef56GH78ij90', { readable: false, ...placed }) + const pending = await release('pp12CD34ef56GH78ij90', { readable: false, first_article: 990, last_article: 1000, posted_at: new Date(settled.getTime() + 86400_000 - 3600_000) }) + const fresh = await release('zz12CD34ef56GH78ij90', { readable: false, settled_at: new Date(), ...placed }) + const spotted = await release('yy12CD34ef56GH78ij90', { readable: false, ...placed }) await db.table('release_spots').insert({ release_id: spotted, spot_id: 's@x', files: 1 }) const round = await new ReleaseJudge().round() @@ -82,6 +92,7 @@ test.group('ReleaseJudge', (group) => { assert.equal(verdicts.get(locked), 'locked') assert.isUndefined(verdicts.get(unlocked)) assert.equal(verdicts.get(unusable), 'unusable') + assert.isUndefined(verdicts.get(pending)) assert.isUndefined(verdicts.get(fresh)) assert.isUndefined(verdicts.get(spotted)) assert.equal(round.rules.repeated.added, 20)