fix: silme fonksiyonlarında ShortVideo FK ihlali (kanal/segment/candidate sil hata veriyordu)

Faz 2'de ShortVideo eklenirken deleteRawSegment/deleteCandidateSegment/
deleteChannel güncellenmemiş — candidate_id FK'sı yüzünden bir short'u
olan candidate silinmeye çalışılınca Postgres reddediyordu. Şimdi her
üç yol da candidate'leri silmeden önce ilişkili ShortVideo satırlarını
(+ render edilmiş dosyalarını) temizliyor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 14:03:54 +03:00
co-authored by Claude Sonnet 5
parent 43ccbd9ec7
commit d045b24c85
+17 -2
View File
@@ -22,10 +22,22 @@ export async function addChannel(formData: FormData) {
revalidatePath("/"); revalidatePath("/");
} }
/** ShortVideo has a required FK to CandidateSegment (candidate_id) — every deletion path that removes candidates must clear their shorts (row + rendered file) first, or Postgres rejects the candidate delete. */
async function deleteShortsForCandidates(candidateIds: string[]): Promise<void> {
if (candidateIds.length === 0) return;
const shorts = await prisma.shortVideo.findMany({ where: { candidateId: { in: candidateIds } } });
await prisma.shortVideo.deleteMany({ where: { candidateId: { in: candidateIds } } });
await Promise.all(shorts.filter((s) => s.filePath).map((s) => unlink(s.filePath!).catch(() => {})));
}
export async function deleteRawSegment(segmentId: string) { export async function deleteRawSegment(segmentId: string) {
const segment = await prisma.rawSegment.findUnique({ where: { id: segmentId } }); const segment = await prisma.rawSegment.findUnique({
where: { id: segmentId },
include: { candidates: true },
});
if (!segment) return; if (!segment) return;
await deleteShortsForCandidates(segment.candidates.map((c) => c.id));
await prisma.candidateSegment.deleteMany({ where: { rawSegmentId: segmentId } }); await prisma.candidateSegment.deleteMany({ where: { rawSegmentId: segmentId } });
await prisma.rawSegment.delete({ where: { id: segmentId } }); await prisma.rawSegment.delete({ where: { id: segmentId } });
await unlink(segment.filePath).catch(() => {}); await unlink(segment.filePath).catch(() => {});
@@ -35,6 +47,7 @@ export async function deleteRawSegment(segmentId: string) {
} }
export async function deleteCandidateSegment(candidateId: string) { export async function deleteCandidateSegment(candidateId: string) {
await deleteShortsForCandidates([candidateId]);
await prisma.candidateSegment.delete({ where: { id: candidateId } }); await prisma.candidateSegment.delete({ where: { id: candidateId } });
revalidatePath("/segments"); revalidatePath("/segments");
@@ -44,11 +57,13 @@ export async function deleteCandidateSegment(candidateId: string) {
export async function deleteChannel(channelId: string) { export async function deleteChannel(channelId: string) {
const sessions = await prisma.streamSession.findMany({ const sessions = await prisma.streamSession.findMany({
where: { channelId }, where: { channelId },
include: { segments: true }, include: { segments: { include: { candidates: true } } },
}); });
const rawSegmentIds = sessions.flatMap((s) => s.segments.map((seg) => seg.id)); const rawSegmentIds = sessions.flatMap((s) => s.segments.map((seg) => seg.id));
const candidateIds = sessions.flatMap((s) => s.segments.flatMap((seg) => seg.candidates.map((c) => c.id)));
const filePaths = sessions.flatMap((s) => s.segments.map((seg) => seg.filePath)); const filePaths = sessions.flatMap((s) => s.segments.map((seg) => seg.filePath));
await deleteShortsForCandidates(candidateIds);
await prisma.candidateSegment.deleteMany({ where: { rawSegmentId: { in: rawSegmentIds } } }); await prisma.candidateSegment.deleteMany({ where: { rawSegmentId: { in: rawSegmentIds } } });
await prisma.rawSegment.deleteMany({ where: { sessionId: { in: sessions.map((s) => s.id) } } }); await prisma.rawSegment.deleteMany({ where: { sessionId: { in: sessions.map((s) => s.id) } } });
await prisma.streamSession.deleteMany({ where: { channelId } }); await prisma.streamSession.deleteMany({ where: { channelId } });