perf(gmail): narrow review-decision lookup to the single ThreadId #17

Merged
cesnimda merged 1 commits from fix/gmail-review-decision-load-all into main 2026-07-11 20:42:19 +02:00
Showing only changes of commit 6a43227315 - Show all commits
+13 -8
View File
@@ -671,7 +671,9 @@ public sealed class GmailController : ControllerBase
imported++; imported++;
} }
UpsertReviewDecision(await _db.GmailReviewDecisions.Where(x => x.OwnerUserId == ownerUserId).ToListAsync(cancellationToken), ownerUserId, request.ThreadId.Trim(), "linked", job.Id, request.Notes); var suggestedJobReviewDecision = await _db.GmailReviewDecisions
.FirstOrDefaultAsync(x => x.OwnerUserId == ownerUserId && x.ThreadId == request.ThreadId.Trim(), cancellationToken);
UpsertReviewDecision(suggestedJobReviewDecision, ownerUserId, request.ThreadId.Trim(), "linked", job.Id, request.Notes);
await _db.SaveChangesAsync(cancellationToken); await _db.SaveChangesAsync(cancellationToken);
return Ok(new CreatedSuggestedGmailJobDto(job.Id, company.Id, request.ThreadId.Trim(), imported, skipped)); return Ok(new CreatedSuggestedGmailJobDto(job.Id, company.Id, request.ThreadId.Trim(), imported, skipped));
} }
@@ -725,8 +727,9 @@ public sealed class GmailController : ControllerBase
imported++; imported++;
} }
var reviewDecisions = await _db.GmailReviewDecisions.Where(x => x.OwnerUserId == ownerUserId).ToListAsync(cancellationToken); var reviewDecision = await _db.GmailReviewDecisions
UpsertReviewDecision(reviewDecisions, ownerUserId, threadId, "linked", job.Id, request.Note); .FirstOrDefaultAsync(x => x.OwnerUserId == ownerUserId && x.ThreadId == threadId, cancellationToken);
UpsertReviewDecision(reviewDecision, ownerUserId, threadId, "linked", job.Id, request.Note);
await _db.SaveChangesAsync(cancellationToken); await _db.SaveChangesAsync(cancellationToken);
return Ok(new GmailRelinkResultDto(threadId, job.Id, imported, skipped, unlinkedMessages)); return Ok(new GmailRelinkResultDto(threadId, job.Id, imported, skipped, unlinkedMessages));
} }
@@ -752,10 +755,11 @@ public sealed class GmailController : ControllerBase
_db.Correspondences.RemoveRange(messages); _db.Correspondences.RemoveRange(messages);
} }
var reviewDecisions = await _db.GmailReviewDecisions.Where(x => x.OwnerUserId == ownerUserId).ToListAsync(cancellationToken); var reviewDecision = await _db.GmailReviewDecisions
.FirstOrDefaultAsync(x => x.OwnerUserId == ownerUserId && x.ThreadId == threadId, cancellationToken);
var nextDecision = (request.NextDecision ?? "review").Trim().ToLowerInvariant(); var nextDecision = (request.NextDecision ?? "review").Trim().ToLowerInvariant();
if (nextDecision is not ("review" or "suggested" or "rejected")) nextDecision = "review"; if (nextDecision is not ("review" or "suggested" or "rejected")) nextDecision = "review";
UpsertReviewDecision(reviewDecisions, ownerUserId, threadId, nextDecision, null, request.Note); UpsertReviewDecision(reviewDecision, ownerUserId, threadId, nextDecision, null, request.Note);
await _db.SaveChangesAsync(cancellationToken); await _db.SaveChangesAsync(cancellationToken);
return Ok(new GmailUnlinkResultDto(threadId, job.Id, messages.Count, nextDecision)); return Ok(new GmailUnlinkResultDto(threadId, job.Id, messages.Count, nextDecision));
} }
@@ -1065,9 +1069,11 @@ public sealed class GmailController : ControllerBase
existing.UpdatedAt = DateTimeOffset.UtcNow; existing.UpdatedAt = DateTimeOffset.UtcNow;
} }
private void UpsertReviewDecision(List<GmailReviewDecision> decisions, string ownerUserId, string threadId, string decision, int? jobApplicationId, string? note) // Single-thread upsert: callers acting on exactly one ThreadId should load just that row
// (see the FirstOrDefaultAsync call sites below) rather than every review decision for the
// owner just to scan for one match.
private void UpsertReviewDecision(GmailReviewDecision? existing, string ownerUserId, string threadId, string decision, int? jobApplicationId, string? note)
{ {
var existing = decisions.FirstOrDefault(x => x.ThreadId == threadId);
if (existing is null) if (existing is null)
{ {
existing = new GmailReviewDecision existing = new GmailReviewDecision
@@ -1075,7 +1081,6 @@ public sealed class GmailController : ControllerBase
OwnerUserId = ownerUserId, OwnerUserId = ownerUserId,
ThreadId = threadId, ThreadId = threadId,
}; };
decisions.Add(existing);
_db.GmailReviewDecisions.Add(existing); _db.GmailReviewDecisions.Add(existing);
} }