Release keys numbered after the highest number, not the count
Test and deploy / test (push) Successful in 57s
Test and deploy / edge (push) Successful in 1m58s
Test and deploy / deploy (push) Successful in 2m10s

Merges delete releases, so the count of a key's releases fell behind its
numbers (83 releases up to key:129): the 20 numbers tried were all taken
and the range's batch failed for good. Spot releases (spot:key) are not
numbered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-20 18:08:13 +02:00
1 parent 293d9d4b52
commit 705f9c3897
2 files changed
+22 -2

No files matched your search

+10 -2
View File
@@ -246,8 +246,16 @@ class BatchStore {
}
const fresh = part.filter((_, idx) => !joined.has(idx))
if (fresh.length > 0) {
// The first upload of a key keeps the key; later ones are key:2, key:3, …
const { rows: counts } = await trx.rawQuery(`SELECT identity_key, count(*) AS n FROM releases WHERE identity_key = ANY(?) GROUP BY 1`, [[...new Set(fresh.map((r) => r.key))]])
// The first upload of a key keeps the key; later ones are key:2, key:3, … after the highest number: merges
// delete releases, and a count fell behind it (83 releases of a key up to key:129: 20 numbers tried, all
// taken, the range's batch failed for good; LOG.md 2026-10-20 (89)). Spot releases (spot:key) aren't numbered.
const { rows: counts } = await trx.rawQuery(
`SELECT identity_key, max(CASE WHEN release_key = identity_key THEN 1
WHEN left(release_key, length(identity_key) + 1) = identity_key || ':' AND substr(release_key, length(identity_key) + 2) ~ '^[0-9]{1,9}$'
THEN substr(release_key, length(identity_key) + 2)::int END) AS n
FROM releases WHERE identity_key = ANY(?) GROUP BY 1`,
[[...new Set(fresh.map((r) => r.key))]]
)
const taken = new Map<string, number>(counts.map((c: { identity_key: string; n: string }) => [c.identity_key, Number(c.n)]))
const numbered = (r: ReleaseChunk) => {
const n = (taken.get(r.key) ?? 0) + 1
+12
View File
@@ -159,6 +159,18 @@ test.group('BatchStore', (group) => {
assert.deepEqual(keys, [first.identity_key, `${first.identity_key}:3`])
})
test('a re-upload is numbered after the highest number, not into the holes merges left', async ({ assert }) => {
for (let day = 0; day < 4; day++) {
await storeIn(GROUP, 1 + day * 100_000, upload(10 + day * 100_000, 'Some.Show.S01E01.1080p.mkv', 2, 'Some.Show.S01E01.1080p [1/1]', `2026-10-0${day * 2 + 1}T10:00:00Z`))
}
const [first] = await releasesOf()
// Merged away: key:2 and key:3 gone, key and key:4 left.
await db.from('releases').whereIn('release_key', [`${first.identity_key}:2`, `${first.identity_key}:3`]).delete()
await storeIn(GROUP, 400_001, upload(400_010, 'Some.Show.S01E01.1080p.mkv', 2, 'Some.Show.S01E01.1080p [1/1]', '2026-10-09T10:00:00Z'))
const keys = (await releasesOf()).map((r) => r.release_key.split(':')[1] ?? '1')
assert.deepEqual(keys, ['1', '4', '5'])
})
test('a small release of sidecars only is marked for the sidecar fold', async ({ assert }) => {
await storeIn(GROUP, 1_000_000, [
...upload(1_000_000, 'Murdoch Mysteries S8D1.nzb', 1, '[00/80]', '2026-10-05T10:00:00Z'),