mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
d6d5f856a6
Our own tooling can now queue a repo's files onto a model version in one call and poll, rather than driving the moderator page by hand. `WEBHOOK_TOKEN` guards it, so it is the same internal surface as the rest of `api/admin`. The transfer job attaches each file when its bytes land, which is what makes one call enough: `attachVersionId` and `attachType` are recorded at enqueue — their own columns, because `modelVersionId` means "attached to" and detach clears it. Detach clears the attach target too, or the sweep would re-attach a file a moderator just removed and mint a second `ModelFile` beside the one detach leaves alive. A file whose sha256 we already store is attached without transferring anything. Hugging Face publishes each LFS file's sha before any bytes move, so a text encoder shared by a dozen repos costs one lookup we already run. The match is on the sha and never the filename: `ae.safetensors` names different bytes in different repos, and the wrong weights on a version stay invisible until someone generates. The attach reads the primary. It runs microseconds after its own completion write, and a replica that had not caught up reported the row as still transferring — recorded as a permanent failure, which the sweep's `error: null` filter then excluded from recovery forever. The sweep takes the same claim the transfer does and runs inside the job's deadline. Unclaimed, two runs could both pass its read and create a file, with `linkImportToFile` picking a winner only after both existed. `createFileHandler`'s body is now `createModelFile`, taking `userId`, `isModerator` and `track` rather than a request context, because a cron tick has no session to borrow. The tRPC path passes its own session through. Both migrations are applied to production. The second is a partial index for the sweep, which orders by `completedAt` — a column no other index covers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015cyrXpr87t9Tj3bnzRrUhp