import db from '@adonisjs/lucid/services/db' /** Noted releases taken per transaction. */ const BATCH = 2000 /** * Release completeness (D24) for releases whose files or par2 listing * changed: triggers only note them in release_dirty (a release can be noted * thousands of times between sweeps), and gc:scheduler recomputes each * noted release once every RELEASE_COMPLETE_INTERVAL_MS (LOG.md 2026-10-06 (6)). */ class ReleaseCompleteness { /** Recomputes all noted releases; returns how many distinct releases were checked. */ async sweep(): Promise { let checked = 0 for (;;) { const done = await db.transaction(async (trx) => { // Taken and recomputed in one transaction: a failure leaves the notes for the next sweep. const { rows } = await trx.rawQuery( `DELETE FROM release_dirty WHERE ctid = ANY(ARRAY(SELECT ctid FROM release_dirty LIMIT ?)) RETURNING release_id`, [BATCH] ) const ids: number[] = [...new Set(rows.map((row: { release_id: string }) => Number(row.release_id)))] if (ids.length > 0) { await trx.rawQuery(`SELECT recompute_release_complete(id) FROM unnest(?::bigint[]) AS id`, [ids]) } checked += ids.length return rows.length < BATCH }) if (done) return checked } } } export default new ReleaseCompleteness()