Lärarguide · Lektion 7 av 10

Transaktioner & concurrency

Optimistic concurrency, Polly-retry, idempotency-tabell, TransactionScope för exactly-once. Det tekniskt svåraste momentet i kursen — ta tid.

V4 Mån
Vecka / Dag
4 h
Total tid
110 min
Teori
120 min
Workshop

Mål

Agenda

0:00
Recap projektioner. Race-condition-demo: två trådar uppdaterar samma konto.
0:20
Teori: optimistic vs pessimistic concurrency.
0:50
Teori: Polly-retry, exponential backoff, jitter.
1:20
Teori: idempotency-tabell + TransactionScope (exakt-en-gång).
1:50
Paus 15 min
2:05
Workshop: lägg in concurrency-handling. Race-test bevisar funktion.
3:45
Outbox-mönstret kort (förhandstitt mot saga i L9).
4:00
Slut

Talartips

Gör race-condition-demon live. Visa hur två POSTs samtidigt får "fel" resultat utan concurrency-skydd. Det skapar känslomässig motivation för lösningen.
Polly med jitter — visa varför pure exponential backoff är dåligt (thundering herd). Lägg in random ±25 %.
TransactionScope är förvirrande. Rita på whiteboard: två databasoperationer in i samma scope — antingen båda eller ingen.

Workshop

  1. Visa misslyckad AppendToStream med fel expected-version → WrongExpectedVersionException.
  2. Wrap:a den i egen ConcurrencyConflictException.
  3. Lägg in Polly: 3 retries, exponential backoff (100 ms, 200, 400) + jitter.
  4. Skapa dbo.IdempotencyKeys-tabell.
  5. Lägg TransactionScope runt: skriv event + uppdatera read model + uppdatera checkpoint.
  6. Race-test: 50 parallella POSTs till samma konto — verifiera att alla räknas och att inga events tappas.

Snabba

  • Mät hur många retries som triggas. Logga distribution.
  • Implementera outbox-tabell.

Stöd

  • Para för pair-programming.
  • Tillhandahåll race-test som färdig kod att köra.

FAQ

Varför inte pessimistic lock?
Skalbarhet. Pessimistic blockerar — optimistic försöker och rullar tillbaka vid konflikt. För majoriteten av användningar är konflikter sällsynta.
Hur många retries är "rätt"?
3 är vanligt. Mer än 5 betyder att kön (L8) borde användas istället för att eliminera konflikter.
Är TransactionScope inte föråldrat?
Nej, det är fullt supportat i .NET 10. Det är bara MSDTC (distribuerad) som man undviker — vi använder lokal lättviktstransaktion mot en databas.
Fallgrop Studenter glömmer att TransactionScope kräver TransactionScopeAsyncFlowOption.Enabled vid async-kod. Lägg in i alla exempel.
Hemuppgift Soloprojekt 1 lektion 07 (race-test + retry-mätning).
Förberedelse till L8 Studenten ska reflektera: "kan vi undvika konflikten istället för att hantera den?" — bro till command-kön.

← L6 L8 →