file_keys: fill in the background, use it once complete
Test and deploy / test (push) Successful in 1m37s
Test and deploy / deploy (push) Successful in 2m23s

Copying all existing keys in the migration read the files rows from the
HDD for over half an hour and held up the deploy. gc:scheduler now copies
them in slices (FILE_KEYS_FILL_SECONDS per sweep) and FileStore checks
every partition until the fill is complete.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-06 14:54:12 +02:00
1 parent 693e6c3244
commit f0ff8e200f
8 files changed
+163 -18

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
import { test } from '@japa/runner'
import db from '@adonisjs/lucid/services/db'
import testUtils from '@adonisjs/core/services/test_utils'
import FileKeys from '#services/FileKeys'
import FileStore from '#services/FileStore'
const file = (key: string, name: string) => {
const now = new Date()
return { file_key: key, filename: name, poster: 'x', date: now.getTime(), parts: 1, groups: '[]', segments: [], created_at: now, updated_at: now }
}
test.group('file_keys', (group) => {
group.each.setup(() => testUtils.db().withGlobalTransaction())
group.each.teardown(() => FileKeys.forget())
test('the fill copies keys from before, then file inserts use the filter', async ({ assert }) => {
// A file from before file_keys: in files, not in file_keys.
const [old] = await FileStore.insert([file('fk-old'.padEnd(40, '0'), 'old.bin')])
await db.rawQuery(`DELETE FROM file_keys WHERE key_hash = hashtextextended(?, 0)`, ['fk-old'.padEnd(40, '0')])
await db.from('file_keys_fill').where('id', 1).update({ next_id: 0, until_id: null, complete: false })
FileKeys.forget()
// Not complete: every partition is checked, so the old key is found anyway.
assert.isFalse(await FileKeys.complete())
assert.lengthOf(await FileStore.insert([file('fk-old'.padEnd(40, '0'), 'again.bin')]), 0)
const filled = await FileKeys.fill(60_000)
assert.isTrue(filled.complete)
assert.isAtLeast(filled.untilId, old.id)
const [{ n }] = (await db.rawQuery(`SELECT count(*) AS n FROM file_keys WHERE key_hash = hashtextextended(?, 0)`, ['fk-old'.padEnd(40, '0')])).rows
assert.equal(Number(n), 1)
// Complete: the filter says the old key may exist, the partitions confirm it; a new key goes in.
assert.isTrue(await FileKeys.complete())
assert.lengthOf(await FileStore.insert([file('fk-old'.padEnd(40, '0'), 'again.bin')]), 0)
assert.lengthOf(await FileStore.insert([file('fk-new'.padEnd(40, '0'), 'new.bin')]), 1)
// And the trigger put the new one in file_keys.
const [{ m }] = (await db.rawQuery(`SELECT count(*) AS m FROM file_keys WHERE key_hash = hashtextextended(?, 0)`, ['fk-new'.padEnd(40, '0')])).rows
assert.equal(Number(m), 1)
})
})