fix(core): race-safe matching, visibility-checked ID matches, child-preserving merges
- migration 0002: unique index on works (parent_id, position) - matchWork retries the whole transaction on a unique violation (3 attempts) - addMissingExternalIds uses ON CONFLICT DO NOTHING - ID matches only return shared works or the user's own; private works cannot carry external ids - adminMergeWorks requires shared works and repoints non-colliding children - draft is computed for the aliased work id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a46fb60eee
commit
437ca143e5
9 files changed
+270
-18
No files matched your search
@@ -0,0 +1,16 @@
|
||||
import type { Kysely } from "kysely";
|
||||
import type { Migration } from "kysely/migration";
|
||||
|
||||
/**
|
||||
* One child per (parent, position), so concurrent matches cannot duplicate seasons or episodes.
|
||||
* NULLs are distinct on both dialects: top-level works and children without a position are unaffected.
|
||||
*/
|
||||
export const worksPositionUnique: Migration = {
|
||||
async up(db: Kysely<any>) {
|
||||
await db.schema.createIndex("works_parent_id_position_uq").unique().on("works").columns(["parent_id", "position"]).execute();
|
||||
},
|
||||
|
||||
async down(db: Kysely<any>) {
|
||||
await db.schema.dropIndex("works_parent_id_position_uq").execute();
|
||||
},
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { Migration } from "kysely/migration";
|
||||
import { initial } from "./0001_initial.ts";
|
||||
import { worksPositionUnique } from "./0002_works_position_unique.ts";
|
||||
|
||||
/** All migrations, keyed by sortable name. Imported statically so bundles need no filesystem. */
|
||||
export const migrations: Record<string, Migration> = {
|
||||
"0001_initial": initial,
|
||||
"0002_works_position_unique": worksPositionUnique,
|
||||
};
|
||||
Reference in new issue
Block a user