From 27866091bf5056d3b582038592705237a698ad62 Mon Sep 17 00:00:00 2001 From: Froidefond Julien Date: Wed, 25 Feb 2026 13:27:57 +0100 Subject: [PATCH] =?UTF-8?q?perf:=20optimisations=20DB=20=E2=80=94=20batch?= =?UTF-8?q?=20queries=20et=20index?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - createEvaluation: remplace N create() par un createMany() (N→1 requête) - updateEvaluation: regroupe les upserts en $transaction() parallèle - Ajout d'index sur Evaluation.evaluatorId, Evaluation.templateId, EvaluationShare.userId et AuditLog.evaluationId Co-Authored-By: Claude Sonnet 4.6 --- .../migration.sql | 11 ++++ prisma/schema.prisma | 6 ++ src/actions/evaluations.ts | 62 ++++++++++--------- 3 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 prisma/migrations/20260225122717_add_performance_indexes/migration.sql diff --git a/prisma/migrations/20260225122717_add_performance_indexes/migration.sql b/prisma/migrations/20260225122717_add_performance_indexes/migration.sql new file mode 100644 index 0000000..b9a5759 --- /dev/null +++ b/prisma/migrations/20260225122717_add_performance_indexes/migration.sql @@ -0,0 +1,11 @@ +-- CreateIndex +CREATE INDEX "AuditLog_evaluationId_idx" ON "AuditLog"("evaluationId"); + +-- CreateIndex +CREATE INDEX "Evaluation_evaluatorId_idx" ON "Evaluation"("evaluatorId"); + +-- CreateIndex +CREATE INDEX "Evaluation_templateId_idx" ON "Evaluation"("templateId"); + +-- CreateIndex +CREATE INDEX "EvaluationShare_userId_idx" ON "EvaluationShare"("userId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 837c1fe..03b92ca 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -66,6 +66,9 @@ model Evaluation { isPublic Boolean @default(false) // visible par tous (ex. démo) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + + @@index([evaluatorId]) + @@index([templateId]) } model EvaluationShare { @@ -77,6 +80,7 @@ model EvaluationShare { createdAt DateTime @default(now()) @@unique([evaluationId, userId]) + @@index([userId]) } model DimensionScore { @@ -106,4 +110,6 @@ model AuditLog { newValue String? userId String? createdAt DateTime @default(now()) + + @@index([evaluationId]) } diff --git a/src/actions/evaluations.ts b/src/actions/evaluations.ts index 67dfac4..e67e974 100644 --- a/src/actions/evaluations.ts +++ b/src/actions/evaluations.ts @@ -72,11 +72,12 @@ export async function createEvaluation(data: { }, }); - for (const dim of template.dimensions) { - await prisma.dimensionScore.create({ - data: { evaluationId: evaluation.id, dimensionId: dim.id }, - }); - } + await prisma.dimensionScore.createMany({ + data: template.dimensions.map((dim) => ({ + evaluationId: evaluation.id, + dimensionId: dim.id, + })), + }); revalidatePath("/dashboard"); return { success: true, data: { id: evaluation.id } }; @@ -177,30 +178,33 @@ export async function updateEvaluation(id: string, data: UpdateEvaluationInput): } if (dimensionScores && Array.isArray(dimensionScores)) { - for (const ds of dimensionScores) { - if (ds.dimensionId) { - await prisma.dimensionScore.upsert({ - where: { - evaluationId_dimensionId: { evaluationId: id, dimensionId: ds.dimensionId }, - }, - update: { - score: ds.score, - justification: ds.justification, - examplesObserved: ds.examplesObserved, - confidence: ds.confidence, - candidateNotes: ds.candidateNotes, - }, - create: { - evaluationId: id, - dimensionId: ds.dimensionId, - score: ds.score, - justification: ds.justification, - examplesObserved: ds.examplesObserved, - confidence: ds.confidence, - candidateNotes: ds.candidateNotes, - }, - }); - } + const validScores = dimensionScores.filter((ds) => ds.dimensionId); + if (validScores.length > 0) { + await prisma.$transaction( + validScores.map((ds) => + prisma.dimensionScore.upsert({ + where: { + evaluationId_dimensionId: { evaluationId: id, dimensionId: ds.dimensionId }, + }, + update: { + score: ds.score, + justification: ds.justification, + examplesObserved: ds.examplesObserved, + confidence: ds.confidence, + candidateNotes: ds.candidateNotes, + }, + create: { + evaluationId: id, + dimensionId: ds.dimensionId, + score: ds.score, + justification: ds.justification, + examplesObserved: ds.examplesObserved, + confidence: ds.confidence, + candidateNotes: ds.candidateNotes, + }, + }) + ) + ); } }