fix(artists-api): create artist + discography atomically

Wrap the WatchedArtist.create + MonitoredRelease.createMany in a
$transaction so a mid-write failure can't leave a followed artist with
no releases (a state the 409 duplicate-follow guard would then wedge).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan
2026-07-12 10:42:42 +02:00
parent a07e791368
commit 33a1ed9cc4
+8 -3
View File
@@ -50,11 +50,14 @@ export async function POST(request: Request) {
return Response.json({ error: "MusicBrainz unavailable" }, { status: 502 }); return Response.json({ error: "MusicBrainz unavailable" }, { status: 502 });
} }
const artist = await prisma.watchedArtist.create({ data: { mbid, name: name.trim() } }); // Create the artist and its discography atomically so a mid-write failure can't leave
// a followed artist with no releases (which the 409 guard above would then wedge).
const artist = await prisma.$transaction(async (tx) => {
const created = await tx.watchedArtist.create({ data: { mbid, name: name.trim() } });
if (releases.length > 0) { if (releases.length > 0) {
await prisma.monitoredRelease.createMany({ await tx.monitoredRelease.createMany({
data: releases.map((r) => ({ data: releases.map((r) => ({
watchedArtistId: artist.id, watchedArtistId: created.id,
artistMbid: mbid, artistMbid: mbid,
artistName: name.trim(), artistName: name.trim(),
rgMbid: r.rgMbid, rgMbid: r.rgMbid,
@@ -67,6 +70,8 @@ export async function POST(request: Request) {
skipDuplicates: true, skipDuplicates: true,
}); });
} }
return created;
});
return Response.json( return Response.json(
{ id: artist.id, mbid: artist.mbid, name: artist.name, releaseCount: releases.length }, { id: artist.id, mbid: artist.mbid, name: artist.name, releaseCount: releases.length },
{ status: 201 }, { status: 201 },