Loyalty anniversary bonus icin iki discount code aldim applyLoyalty cron duplikat belt-and-suspenders — QQ-B F2 (PR #553)
Sivas Merkez Cumhuriyet Caddesi 38-yas Sivas Koftesi + Kelle Paca 40-cover 15-yil geleneksel Sivas koftesi + 7 saat pisirilen kelle paca corbasi sahibi Huseyin thMenu Pro 13 ay anniversary kutlamasi. Pro tier abonelere 12. ay bir-defalik thMenu Anniversary Bonus %10 Stripe discount code uretiliyor. Huseyin gelen kutusunda iki ayri thMenu Loyalty Bonus emaili buldu codes HSY-ANNIV-A2X9F + HSY-ANNIV-B7K3L. Stripe Customer Portal acti ilki applied %10 ikinci revoked. Iki kod uretildi sirf birisi gecerli olmali. Support yazdi. Engineering 6-ay applyLoyalty cron log audit 28 user_id iki active loyalty_discounts row 56 Stripe promotion_code yarisi post-hoc revoked. Adli analiz cloudflare/src/cron-jobs/apply-loyalty.ts cron 30-dakika bir Pro+ abonelerden 12 ay tamamlamis user_id select Stripe promotion_code yarat insertEnvelope SELECT eligible WHERE pro_started_at < NOW() - 12 months AND no_loyalty_row pseudo-code Stripe API POST promotion_codes idempotency-key floor(Date.now() / 86400000 / 30) bazli epoch_month boundary. Epoch month boundary edge case floor(Date.now() / 86400000 / 30) flips between X and X+1 within minutes between cron ticks. Iki paralel tick farkli idempotency-key Stripe iki ayri promotion_code yarat. 3 yanlis teori (1) Stripe API ayni payload duplicate sense Stripe Idempotency-Key bekliyor inferred dedup yok; (2) Supabase INSERT loyalty_discounts UNIQUE constraint yetmez ON CONFLICT IGNORE INSERT engeller cron exception throw retry sonra promotion_code Stripe duplicate uretildi zaten; (3) cron_idempotency_claims wrap ayri tick blocks ayni gun ama bir tick claim aldi crashed monthly_epoch onceki ayda kaldi yeni ay claim cleared. Dogru pattern Stripe Idempotency-Key stable user_id + resource_id base 24h Stripe server-side dedup + Supabase loyalty_discounts partial UNIQUE WHERE status IN (applied, skipped) DB belt-and-suspenders + applyLoyalty cron try/catch 23505 unique_violation continue. PR #553 batch QQ-B F2 2-layer fix Layer 1 Supabase migration 20260523000003_loyalty_discounts_uniq CREATE UNIQUE INDEX uq_loyalty_discounts_active ON loyalty_discounts(user_id) WHERE status IN (applied, skipped) revoked exempt legitimate cancel + resubscribe flow earn fresh loyalty row. Layer 2 applyLoyalty cron try/catch PostgreSQL 23505 unique_violation continue iki tick INSERT race UNIQUE catch + bonus pre-flight Supabase SELECT loyalty_discounts WHERE user_id + status IN (applied, skipped) maybeSingle Stripe API call onunde block quota burn forever Stripe promotion_codes 200 promo code/account-limit ucretsiz dolar Stripe. Production audit + backfill Huseyin ilk kod (HSY-ANNIV-A2X9F) gecerli ikinci kod (HSY-ANNIV-B7K3L) Stripe Revocations API + Supabase status='revoked' patch + email apology + 1-ay Pro tier credit. 28 user 56 Stripe promotion_code 28 revoke production-wide audit + apology + credit. Post-deploy 60-day 0 yeni duplicate loyalty_discounts row applyLoyalty cron parallel tick UNIQUE constraint catch 23505 continue Stripe API never called duplicate quota saved. Eilidh Glasgow West End Byres Road 42-yo 11-yr Glasgow Old Town Brewery 50-cover Scottish ale + craft beer pub paralel pattern iki discount code 08:47 + 08:49 UTC codes EIL-ANNIV-Q4R7P + EIL-ANNIV-X9M2B ayni fix shipped 1-ay Pro credit. Pattern Cloudflare cron at-least-once delivery external API write zero idempotency = orphan external state Stripe POST promotion_codes Resend email send Wise transfer BOTH idempotency-key header AND DB-side UNIQUE constraint zorunlu tek tane yetmez. Sibling sweep applyLoyalty QQ-B F2 + scanFor1099Threshold PR #536 LL + aff-postback-dispatch PR #493 R + order-refund PR #311 + #328 + customer-magic-link PR #335 + Stripe webhook checkout PR #313 + #519. Implementation pattern (1) stable Stripe Idempotency-Key user_id + resource_id 24h server-side dedup, (2) Supabase/D1 partial UNIQUE constraint belt-and-suspenders, (3) INSERT error catch 23505 collapses already_processed/replay branch. PR #553 referans.
thMenu Ekibi
thmenu.com
Faydalı buldunuz mu? Paylaşın.
İlgili makaleler
Müşteri Aboneliğini Düşürünce Eski Özellikler Ne Olur? — SaaS Sessiz Feature-Drift Problemi
Çoğu SaaS abonelik tier’ı düştüğünde tek satır kod çalıştırır ama eski özellikle…
JWT alg-confusion atağı — Supabase HS256'dan RS256/JWKS'e geçince eski verifier'lar neden yıkılır?
JWT header'ı decode etmeyen verifier'lar `alg=none` ve `alg-confusion` saldırıla…
Her bakiye değişikliğinin neden bir 'journal row'u olmalı? — SaaS finansal audit'in temel taşı
SaaS bakiyeleri tek satır UPDATE ile yönetince "drift var ama HANGİ mutasyon yan…