import db from '@adonisjs/lucid/services/db' /** Hours a complete provisional release stays open for its window's continuation before it is settled here. */ export const SETTLE_COMPLETE_HOURS = 6 /** * Provisional releases (REBUILD.md, "Voyager 3: window indexing", 2): a release the window hadn't closed on at a * lease's end is written with `settled_at` null, for the window's continuation to finish. A continuation may * never come (the range-lease path of the first run left 109k such rows, LOG.md (118); a group's next lease is * hours away), and the catalog shows the release as still collecting. A complete one — every file its counter * announced found — can't gain a counted file any more, so once it has been quiet for SETTLE_COMPLETE_HOURS it is * settled here, as the finish would: `settled_at` set (the judge's trigger fires on it), its waiting probe * candidates made claimable. Incomplete ones keep waiting: the continuation adds their files. */ class Settler { async settleComplete(quietHours = SETTLE_COMPLETE_HOURS): Promise { return db.transaction(async (trx) => { const { rows } = await trx.rawQuery( `UPDATE releases SET settled_at = now() WHERE settled_at IS NULL AND complete AND first_seen_at < now() - make_interval(hours => ?) AND last_posted_at < now() - make_interval(hours => ?) RETURNING id`, [quietHours, quietHours] ) if (rows.length > 0) await trx.rawQuery( `UPDATE probe_candidates pc SET ready = true, unreadable = NOT r.readable FROM releases r WHERE pc.release_id = ANY(?::bigint[]) AND r.id = pc.release_id AND pc.status = 'waiting' AND NOT pc.ready`, [rows.map((r: { id: string }) => Number(r.id))] ) return rows.length }) } } export default new Settler()