@@ -5,22 +5,31 @@ export async function getOrCreateRepoByUrl(
55 url : string ,
66 host : string ,
77) : Promise < { id : string ; changedFields : string [ ] } > {
8- const row : { id : string ; created : boolean } = await qx . selectOne (
9- `
10- WITH ins AS (
11- INSERT INTO repos (url, host) VALUES ($(url), $(host))
12- ON CONFLICT (url) DO NOTHING
13- RETURNING id
14- )
15- SELECT id::text AS id, true AS created FROM ins
16- UNION ALL
17- SELECT id::text AS id, false AS created
18- FROM repos
19- WHERE url = $(url) AND NOT EXISTS (SELECT 1 FROM ins)
20- ` ,
8+ // Repos are shared across packages (every package in a monorepo points at one repo)
9+ // so this is by far the common case
10+ const existing : { id : string } | null = await qx . selectOneOrNone (
11+ `SELECT id::text AS id FROM repos WHERE url = $(url)` ,
12+ { url } ,
13+ )
14+ if ( existing ) return { id : existing . id , changedFields : [ ] }
15+
16+ // Not seen yet — try to create it. ON CONFLICT DO NOTHING so a concurrent ingest lane creating
17+ // the same shared repo doesn't raise a unique violation.
18+ const inserted : { id : string } | null = await qx . selectOneOrNone (
19+ `INSERT INTO repos (url, host) VALUES ($(url), $(host))
20+ ON CONFLICT (url) DO NOTHING
21+ RETURNING id::text AS id` ,
2122 { url, host } ,
2223 )
23- return { id : row . id , changedFields : row . created ? [ 'repos.url' , 'repos.host' ] : [ ] }
24+ if ( inserted ) return { id : inserted . id , changedFields : [ 'repos.url' , 'repos.host' ] }
25+
26+ // Lost the race: another lane committed the same url between our SELECT and INSERT, so
27+ // ON CONFLICT DO NOTHING returned no row. Re-read in a fresh statement — under READ COMMITTED
28+ const row : { id : string } = await qx . selectOne (
29+ `SELECT id::text AS id FROM repos WHERE url = $(url)` ,
30+ { url } ,
31+ )
32+ return { id : row . id , changedFields : [ ] }
2433}
2534
2635export async function upsertPackageRepo (
0 commit comments