Back to all reviewers

Enforce atomic database operations

elie222/inbox-zero
Based on 6 comments
TypeScript

Replace check-then-act patterns with atomic database operations to prevent race conditions in concurrent environments. Use transactions for multi-step operations and leverage database-level constraints instead of application-level checks.

Concurrency TypeScript

Reviewer Prompt

Replace check-then-act patterns with atomic database operations to prevent race conditions in concurrent environments. Use transactions for multi-step operations and leverage database-level constraints instead of application-level checks.

Example - Transform this race-prone code:

// DON'T: Check-then-act pattern
const existing = await prisma.newsletter.findUnique({
  where: { email_userId: { email, userId } }
});
if (!existing?.analyzed) {
  await prisma.newsletter.create({
    data: { email, userId, analyzed: true }
  });
}

Into atomic operation:

// DO: Use upsert for atomic operation
await prisma.newsletter.upsert({
  where: { email_userId: { email, userId } },
  update: { analyzed: true },
  create: { email, userId, analyzed: true }
});

// DO: Use transactions for multi-step operations
await prisma.$transaction(async (tx) => {
  const result = await tx.newsletter.findUnique({/*...*/});
  if (result) {
    await tx.newsletter.update({/*...*/});
  }
});

Key practices:

  • Use upsert instead of separate find/create
  • Wrap related operations in transactions
  • Handle unique constraint violations (e.g., Prisma P2002 errors)
  • Add database-level constraints rather than relying on application checks
  • Consider using advisory locks for complex operations
6
Comments Analyzed
TypeScript
Primary Language
Concurrency
Category

Source Discussions