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

Affiliate tier history'de iki aynı anda Gold promotion — evaluateTier OCC race (PR #621 FFF F3)

Aydin Kusadasi nda 32 yaslarinda TikTok food creator + dijital pazarlamaci Bahar (@bahareats, 67k takipci Ege niche), 18 ay thMenu affiliate program. Pro+ Gold tier 4 ay once auto-promote (PR #644 V evaluateTier 90-day rolling commission $1,500 esigi). Dashboard tier_events panel: **iki ayri "Promoted to Gold" event** ikisi de 2026-01-22 14:18:34 UTC. Bahar support a yazdi. Forensik: 14:18:32 Restaurant A $290/yil annual + 14:18:33 Restaurant B $29/ay monthly iki ayri Stripe invoice.paid event evt_aaa111 ve evt_bbb222 (iki ayri legitimate event). Affiliate commission webhook handler her event icin INSERT affiliate_commissions + fire-and-forget evaluateTier(affiliateId). **14:18:34** iki concurrent evaluateTier invocation A.012 + B.028 (16ms apart): ikisi de SELECT commission_rate → 20 (Bronze) ayni snapshot, SUM commission_amount 90 days → $1,502 ayni esik cross, compute new tier → 25 (Gold), UPDATE affiliate_profiles + INSERT tier_events. **2 duplicate rows landed**. commission_rate 25 e iki kez idempotent ama redundant. Wrong theory: webhook idempotent degil? Stripe webhook idempotency claim mekanizmasi (PR #330) iki ayri event_id (evt_aaa, evt_bbb) iki legitimate event her biri 1 kez islendi. Problem evaluateTier concurrent invocation. **Doğru teori**: evaluateTier read-then-write OCC race-guard yok. Worst case race window genis (invoice.paid + customer.subscription.updated concurrent) farkli tier hesaplaniyor last-writer-wins yanlis tier. **PR #621 batch FFF F3** fix Supabase OCC race-guard via .eq() chain: `await supabase.from("affiliate_profiles").update({ commission_rate: newRate }).eq("id", affiliateId).eq("commission_rate", currentRate).select("id");` PostgreSQL atomic check-and-set semantic. Returned data empty → race-lost branch → tier_events INSERT skip + [BEACON:evaluate_tier_race_lost] structured log. Race-won branch → INSERT tier_events + audit. Beklenen: 2 concurrent invocation 1 wins 1 loses. Backfill audit duplicate detect: SELECT affiliate_id, from_rate, to_rate, COUNT(*) GROUP BY DATE_TRUNC("minute", created_at) HAVING COUNT > 1. 23 affiliate 47 duplicate tier_events rows. Script soft-delete status="superseded" + dashboard rendering filter. Bahar 2 row → 1 row + email + Hall of Fame + 2-ay Pro tier. Pattern: **Stripe webhook lar (ve diger event-driven systems) parallel fire edebilir. Webhook handler larindaki fire-and-forget downstream function lar (analytics aggregator, tier evaluator, score recalculator) concurrent invocation handling icin OCC race-guard a sahip olmali. Supabase de .eq("column", priorValue) chain, D1 de WHERE column = ? + meta.changes check. Race-lost branch structured BEACON log + side-effect skip.** Implementation checklist: (1) webhook handler fire-and-forget downstream call audit; (2) read .select() priorValue local store; (3) compute new value; (4) UPDATE WHERE priorValue match; (5) returned-data empty/meta.changes 0 = race-lost; (6) race-lost branch skip downstream INSERTs + BEACON log; (7) race-won branch INSERT + audit; (8) Sentry alert rule [BEACON:race_lost_xxx] 5+/hour threshold; (9) periodic backfill audit duplicate side-effect rows cleanup. Greta Hamburg Sternschanze German-language restaurant-tech niche version aynı flow.

th

thMenu Ekibi

thmenu.com

Faydalı buldunuz mu? Paylaşın.