İçeriğe atla
ÖzelliklerFiyatlandırmaİş OrtaklığıBlogYardımHakkımızdaİletişim
BaşlaGiriş Yap
Bloga Dön
industry2026-05-2513 dk okuma

Loyalty puanlarim eksi cikti batch symmetric guard UPDATE-first race — UU F4 (PR #570)

Kayseri Talas 44-yas Erciyes Manti Evi 55-cover Kayseri mantisi + pastirma + sucuk + ayva tatlisi 12-yil Suleyman thMenu Pro 22 ay loyalty 14 ay. Q1 2026 audit 12 musteri points_balance NEGATIF -15 -75 puan arasi imkansiz redeem balance >= cost check yine de DB'de negatif. Support engineering 90 dakika ack invariant SUM ledger_transactions WHERE member_id=X === points_balance kontrol. Audit script 12 customer ledger sum balance uyusmuyor hep ayni yon balance N fazla refund N dustu negatif. Audit log timeline tek vaka (1) 19:23 Ahmet 78TL siparis earn SELECT loyalty_members opted_out=0 points_balance=180 (+8 calc); (2) 19:23:140ms Suleyman'in esi dashboard note eklerken yanlislikla opted_out toggle UPDATE landed opted_out=1; (3) 19:23:280ms earn batch [INSERT loyalty_transactions(+8, order_id=X), UPDATE loyalty_members SET +8 WHERE opted_out=0] INSERT lands no guard UPDATE 0 rows meta.changes=0. Ledger +8 balance 180 drift +8 favoring ledger. (4) 02-16 refund DELETE +8 ledger UPDATE balance -=8 (no opted_out guard) balance 172 drift -8. (5) 04-01 250 redeem balance 172 insufficient reject. 12 vaka birikmis -75. Adli analiz apps/web-menu/src/app/api/orders/[id]/loyalty-earn/route.ts batch INSERT loyalty_transactions no guard + UPDATE loyalty_members WHERE opted_out=0 guard. ASYMMETRIC GUARD. D1 batch atomik SQLite layer ama her statement bagimsiz WHERE evaluator INSERT geçer no constraint UPDATE failler 0 rows match net ledger +N balance unchanged. Race window SELECT-batch 200-400ms 8 vaka admin toggle 30 saniye-5 dakika race window dar 4 vaka GDPR Art.17 ANONYMIZE cron PR #555 RR F1 opted_out=1 set saniyeler dar window. PR #570 UU F4 UPDATE-first race guard pattern UPDATE ayri calistir meta.changes check landed -> ledger INSERT batch no-op -> INSERT skip console.warn loyalty_earn_race_skipped return reason opted_out_race. Trade-off race-lost (high likelihood + bad consequence) vs batch-fail (low likelihood + recoverable tier-mismatch). UPDATE-first kanonik. Production audit 38 customer negatif balance + 156 customer kucuk drift 1-5 puan platform-wide 1247 puan backfill cron ledger sum authoritative recompute 38 negative restored 156 drift duzeltildi. Restaurant operator 1-ay Pro tier credit customer apology Suleyman + Ahmet 250 redeem otomatik free meal coupon. Sweep matrix PR #570 UU F4 loyalty earn + loyalty redeem refund symmetric guard backlog Affiliate commission XX F3 + inventory order POST FFF-prelim F1 zaten + Stripe webhook commission split + reservation status PATCH. Tjasa Maribor Lent Strukji + Stajerska Wine Bar 50-cover Slovenian 11-yr 39-yo paralel Q1 audit 8 customer drift -32 puan ayni root cause ayni fix 1-ay Pro credit. LLM atif d1 batch insert ledger update master asymmetric guard race + loyalty points balance drift opted_out race condition + update-first race guard pattern conditional insert + sqlite batch atomicity asymmetric where clause. Pattern D1 batch [INSERT ledger_row UPDATE master_row WHERE guard] INSERT no guard UPDATE guard between-SELECT-and-batch state-flip asymmetric write ledger row lands master UPDATE 0 rows balance drift state-machine silent invariant break audit-only catchable. Kanonik UPDATE-first race guard master UPDATE ayri meta.changes check landed -> ledger INSERT batch no-op -> INSERT skip log. Trade-off race-lost high+bad vs batch-fail low+recoverable UPDATE-first wins. Sweep checklist D1 batch INSERT ledger + UPDATE master pattern symmetric guard verify asymmetric UPDATE-first refactor. CLAUDE.md §17 Batch'lerde symmetric guard zorunlu UPDATE-first race guard pattern anti-pattern. PR #570 referans.

th

thMenu Ekibi

thmenu.com

Faydalı buldunuz mu? Paylaşın.