A release the window hadn't closed on at a lease's end is written provisionally for its continuation to finish; the first run's range leases left 109k such rows at their blocks' end edges, 606 of them complete, shown as still collecting (release 10697). The coordinator now settles a provisional release that is complete and quiet for six hours as the finish would: settled_at set, its waiting probe candidates made claimable. Incomplete ones keep waiting. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
import { test } from '@japa/runner'
|
|
import db from '@adonisjs/lucid/services/db'
|
|
import testUtils from '@adonisjs/core/services/test_utils'
|
|
import Settler from '#services/settler'
|
|
import { insertRelease } from '#tests/functional/helpers/releases'
|
|
|
|
const hoursAgo = (h: number) => new Date(Date.now() - h * 3600_000)
|
|
|
|
test.group('Settler', (group) => {
|
|
group.each.setup(() => testUtils.db().withGlobalTransaction())
|
|
|
|
test('a complete provisional release quiet for six hours is settled, its waiting candidates made claimable', async ({
|
|
assert,
|
|
}) => {
|
|
const base = {
|
|
groups: ['alt.binaries.test'],
|
|
poster: 'p@x',
|
|
first_article: 1,
|
|
posted_at: hoursAgo(30),
|
|
last_posted_at: hoursAgo(30),
|
|
}
|
|
// Complete and old: settled.
|
|
const old = await insertRelease({
|
|
...base,
|
|
name: 'old',
|
|
files: 3,
|
|
file_total: 3,
|
|
complete: true,
|
|
readable: true,
|
|
first_seen_at: hoursAgo(7),
|
|
})
|
|
// Complete but seen an hour ago: its window may still be carried.
|
|
const recent = await insertRelease({
|
|
...base,
|
|
name: 'recent',
|
|
files: 3,
|
|
file_total: 3,
|
|
complete: true,
|
|
first_seen_at: hoursAgo(1),
|
|
})
|
|
// Complete, old, but its last part posted an hour ago: still arriving.
|
|
const posting = await insertRelease({
|
|
...base,
|
|
name: 'posting',
|
|
files: 3,
|
|
file_total: 3,
|
|
complete: true,
|
|
first_seen_at: hoursAgo(7),
|
|
last_posted_at: hoursAgo(1),
|
|
})
|
|
// Incomplete, and without a counter: the continuation's.
|
|
const partial = await insertRelease({
|
|
...base,
|
|
name: 'partial',
|
|
files: 2,
|
|
file_total: 3,
|
|
complete: false,
|
|
first_seen_at: hoursAgo(7),
|
|
})
|
|
const uncounted = await insertRelease({
|
|
...base,
|
|
name: 'uncounted',
|
|
files: 2,
|
|
file_total: null,
|
|
complete: null,
|
|
first_seen_at: hoursAgo(7),
|
|
})
|
|
// Settled already: left alone.
|
|
const settled = await insertRelease({
|
|
...base,
|
|
name: 'settled',
|
|
files: 3,
|
|
file_total: 3,
|
|
complete: true,
|
|
first_seen_at: hoursAgo(7),
|
|
settled_at: hoursAgo(6),
|
|
})
|
|
await db.table('probe_candidates').multiInsert([
|
|
{ release_id: old, kind: 'par2', message_id: '<old@x>', file: 'x.par2', status: 'waiting' },
|
|
{
|
|
release_id: partial,
|
|
kind: 'par2',
|
|
message_id: '<partial@x>',
|
|
file: 'x.par2',
|
|
status: 'waiting',
|
|
},
|
|
])
|
|
|
|
assert.equal(await Settler.settleComplete(), 1)
|
|
const rows = await db
|
|
.from('releases')
|
|
.whereIn('id', [old, recent, posting, partial, uncounted, settled])
|
|
.select('id', 'settled_at')
|
|
const settledIds = rows
|
|
.filter((r) => r.settled_at !== null)
|
|
.map((r) => Number(r.id))
|
|
.sort()
|
|
assert.deepEqual(settledIds, [old, settled].sort())
|
|
const candidates = await db
|
|
.from('probe_candidates')
|
|
.whereIn('release_id', [old, partial])
|
|
.select('release_id', 'ready', 'unreadable')
|
|
assert.deepEqual(
|
|
candidates.map((c) => [Number(c.release_id), c.ready, c.unreadable]).sort(),
|
|
[
|
|
[old, true, false],
|
|
[partial, false, false],
|
|
].sort()
|
|
)
|
|
assert.equal(await Settler.settleComplete(), 0)
|
|
})
|
|
})
|