Seed batches: insert files and binaries in chunks of 2,000 rows
Test and deploy / test (push) Failing after 3m16s
Test and deploy / deploy (push) Skipped

A batch of a dense range (over ~5,400 files) exceeded Postgres' 65,535
bind parameters per statement, so its post failed with a 500 until the
range was given up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Opus 5.5 committed 2026-10-06 00:01:32 +02:00
1 parent f4ded062df
commit 953bbe9e39
3 files changed
+31 -7

No files matched your search

+10 -2
View File
@@ -36,6 +36,9 @@ export function loadedSegments(stored: Buffer | null): Segment[] {
return stored ? unpackSegments(stored) : []
}
/** Rows per INSERT, well below Postgres' 65,535 bind parameters. */
export const INSERT_ROWS = 2000
class FileStore {
/**
* Inserts files, skipping those whose `file_key` exists. Returns the rows
@@ -66,8 +69,13 @@ class FileStore {
return { ...file, segments: packSegments(sorted), first_message_id: sorted[0]?.id ?? null }
})
if (rows.length === 0) return []
const inserted = await client.knexQuery().table('files').insert(rows).onConflict().ignore().returning(['id', 'filename'])
return inserted.map((row: any) => ({ id: Number(row.id), filename: row.filename }))
// A statement takes at most 65,535 parameters: ~5,400 rows of 12 columns.
const inserted: { id: number; filename: string }[] = []
for (let i = 0; i < rows.length; i += INSERT_ROWS) {
const chunk = await client.knexQuery().table('files').insert(rows.slice(i, i + INSERT_ROWS)).onConflict().ignore().returning(['id', 'filename'])
for (const row of chunk) inserted.push({ id: Number(row.id), filename: row.filename })
}
return inserted
}
}
+7 -5
View File
@@ -1,6 +1,6 @@
import db from '@adonisjs/lucid/services/db'
import IngestService from '#services/IngestService'
import FileStore from '#services/FileStore'
import FileStore, { INSERT_ROWS } from '#services/FileStore'
import SfvService from '#services/SfvService'
import ContentService from '#services/ContentService'
import QueueService from '#services/QueueService'
@@ -78,10 +78,12 @@ class SeedService {
file_id: fileIds.get(file.fileKey) ?? null,
}))
binaries.sort((a, b) => a.file_key.localeCompare(b.file_key))
await knex('binaries')
.insert(binaries)
.onConflict('file_key')
.merge({ file_id: knex.raw('coalesce(binaries.file_id, excluded.file_id)') as any })
for (let i = 0; i < binaries.length; i += INSERT_ROWS) {
await knex('binaries')
.insert(binaries.slice(i, i + INSERT_ROWS))
.onConflict('file_key')
.merge({ file_id: knex.raw('coalesce(binaries.file_id, excluded.file_id)') as any })
}
// As worker:file does for a new file: an SFV posted earlier may list it (D34), then inspection.
const rowById = new Map(rows.map((row) => [fileIds.get(row.file_key), row]))