DDD w rdzeniu iGaming
Platforma iGaming jest złożonym systemem domeny na przecięciu finansów, rozrywki i zgodności. DDD pomaga zachować złożoność: podkreśla ograniczone konteksty, przechwytuje wszechobecny język, chroni niezmienne agregaty, upraszcza integrację poprzez warstwy antykorupcyjne i sprawia, że zachowanie systemu jest przejrzyste poprzez zdarzenia domenowe.
1) Mapa domeny i ograniczone konteksty (projekt strategiczny)
Zalecany rozkład:- Player/KYC Context - rejestracja, weryfikacja, odpowiedzialne limity gry, statusy KYC/AML.
- Kontekst portfela/Księga - salda, rezerwacje, transakcje, wielokrotność, kursy wymiany walut.
- Kontekst zakładów - zakłady/bilety, pary/wyniki, cytaty, rozliczenia, anulowanie.
- Kasyno/Game Round Context - sesje, rundy, plecy, kontrola RTP, limity zakładów.
- Bonus/Promo Context - zasady bonusowe, zakłady, pozyskiwanie funduszy bonusowych, przeciwdziałanie nadużyciom.
- Kontekst ryzyka/oszustwa - punktacja, sygnały behawioralne, blokada/wyzwalacze czasu.
- Kontekst płatności - wpłaty/wypłaty, status bramy płatności, zdarzenia związane z obciążeniem zwrotnym.
- Kontekst zgodności/sprawozdawczości - sprawozdania dla organów regulacyjnych, listy sankcji, audyty.
- Kontekst integracji treści/dostawcy - integracja z dostawcami gier, katalogi, tech. statusy.
- Modele analityczne/czytelnicze - projekcje i prezentacje odczytów produktów.
2) Wszechobecny język: rdzeń terminów
Gracz, sesja, GameRound, zakład/bilet,
Wpis do rejestru, wstrzymanie/rezerwa, rozliczenie,
Bonus Credit/Bonus Balance, Wagering Requirement (Вевдсей),
KYC Tier, Limit (depozyt/sesja/strata), Self-Exclusion,
Dostawca gry, okno RTP, flaga ryzyka, sprawa zgodności.
Nazwy te są również wykorzystywane w kodach, bazie danych, dokumentacji, testach i interfejsach.
3) Kruszywa i niezmienne (projekt taktyczny)
3. 1 Portfel (kruszywo: „Portfel”)
Niezmienne:- Saldo nie wchodzi na terytorium ujemne.
- Rezerwa + dostępne ≤ saldo całkowite.
- Okablowanie jest atomowe i idempotentne (przez 'operation _ id').
- 'Portfel. Rezerwa (kwota, powód, op_id) "→" Rezerwacja portfela "
- 'Portfel. Zobowiązanie (op_id) "→" WalletCommitted "
- 'Portfel. Rollback (op_id) "→" WalletRolled Back"
Granica: Portfel nie wie o Bet/Bonus; obsługuje transakcje delegowania i rezerwy.
3. 2 Zakład/bilet (suma: „Zakład”)
Niezmienne:- Stawka może być akceptowana tylko w oknie aktywnego notowania; Kwota ≤ gracz/limit sesji.
- Po wyrażeniu „Settled” status jest „sfinalizowany”; ponowne obliczenie jest dozwolone tylko poprzez operacje kompensacyjne (nieważne/powtórne) z jasnym audytem.
- 'Założę się. Miejsce (player_id, kwota, cena, op_id) "→" BetPlaced "(тревей Wallet. Rezerwa)
- 'Założę się. Settle (wynik, wypłata) '→' BetSettled '(wymaga Portfel. Commit/Release)
- 'Założę się. Nieważność (powód) "→" BetVoided "
Granica: Zakład nie „wspina się” do Portfela - wywołuje poprzez polecenia/orkiestrę domeny.
3. 3 GameRound (Kruszywo: „Runda”)
Niezmienne:- Każda runda/spin ma unikalny 'round _ id' i powiązaną kwotę zakładu/wygranej.
- Okno RTP nie przekracza określonych progów (na poziomie dostawcy + reguły lokalne).
- 'Okrągły. Zaczęło się ',' Runda. Stawka ',' Okrągły. Wynik ',' Runda. Zamknięte.
3. 4 Bonus (Suma: „BonusGrant”)
Niezmienne:- Vager zmniejsza się tylko z ważnego obrotu, bonusowe odpisy nie wchodzą do debetu.
- Nie jest możliwe umorzenie premii i funduszy rzeczywistych w tym samym czasie nie zgodnie z zasadą pierwszeństwa.
- „Premia przyznana”, „BonusWagered”, „Bonus wygasł”, „Bonus Konwertowany”.
4) Orkiestry, sagi i spójność
Synchroniczny (CP): akceptacja zakładu i rezerwy środków - jeden sposób: 'Zakład. Miejsce '→' Portfel. Rezerwy "(za pośrednictwem zespołu domen/orkiestratora z terminem).
Asynchroniczny (EC): kalkulacja stóp, bonus memoriałowy, analityka - poprzez zdarzenia + outbox.
Wariant TCC: „Reserve” (hold), „Confirm” (commit), „Anuluj” (rollback) dla efektów pieniężnych.
Idempotencja: wszystkie polecenia przenoszą 'operation _ id', konsumenci -' skrzynka odbiorcza '.
5) Warstwy antykorupcyjne (ACL) i integracje
Dostawca ACL: tłumaczenie imprez dostawcy 'SpinResult', 'BonusWin' to internal 'Round. Wynik "," BonusWagered ". Schematy i wersje są wewnątrz ACL.
PSP ACL: normalizacja statusów płatności, idempotencja przez 'psp _ tx _ id', przeniesienie do' LedgerEntry '.
Zgodność ACL: integracja z listami sankcji/RAP - w kontekście zewnętrznym; tylko znormalizowane 'ScreatsUpdated' dostać się do domeny.
Reguła: zewnętrzne słowniki/formaty nie „wyciekają” do jądra.
6) Projekcje i modele odczytu
Profil gracza Czytaj model: KYC statusy, limity, aktywne bonusy, świeże transakcje.
Balances Read Model: Szybkie odczyty dla interfejsu użytkownika/marketingu; źródło - wydarzenia „Portfel”.
Historia zakładu Przeczytaj model: Pagination by Date/Game; źródłem jest 'BetPlaced/Settled'.
Raporty zgodności - zmaterializowane poglądy najemcy/regionu.
Wszystkie projekcje są idempotentne upserts z wersioning i 'as _ of/świeżość'.
7) Wielopoziomowy i wielobranżowy
Wszystkie kluczowe podmioty posiadają "najemcę _ id' oraz (w razie potrzeby)" region ".
Granice danych: gracz, portfel, zakłady - region „domowy”; tylko kruszywa/sprawozdania międzyregionalne.
Sprawiedliwość/kwoty: limity dla zespołów/sek., a przekierowania dla najemców.
Rezydencja/zgodność: dane osobowe i transakcje nie opuszczają regionu.
8) Wybór spójności (PACELC) według kontekstu
Portfel/Ledger - Strong/CP: transakcje linearyzowane, kworum rekordów.
Akceptacja zakładu - synchroniczne potwierdzenie (CP) + szybkie czytanie modeli dla interfejsu użytkownika.
Rozliczenie/Bonus/Analytics - EC z deterministycznym połączeniem/kompensacją.
KYC/Zgodność - może być WE dla statusów, ale zasady „blokowania” są stosowane synchronicznie.
9) Wydarzenia domeny: Umowy i wersja
Minimalny zestaw pól:json
{
"event_id": "uuid",
"event_type": "BetPlaced",
"occurred_at": "timestamp",
"tenant_id": "T123",
"aggregate_id": "BET-...-UUID",
"version": 7,
"payload": { "...domain fields..." },
"schema_version": "v3"
}
Zasady:
- Systemy back/forward-compat; ewolucja poprzez 'schema _ version'.
- „skrzynka” w transakcji ze zmianami domeny; publikacja przez butches z backoff.
10) Przykład przepływu „Zakład z bonusem” (sekwencja słów)
1. "Zakład. Place '(zespół) → sprawdzanie limitów gracza i →' Zasady premii portfela. Rezerwa (real + bonus _ equiv, op_id) "
2. 'BetPlaced' → Czytaj aktualizacje modeli 'Open Wagers'
3. Dostawca publikuje wynik → → "Round ACL. Powstały "
4. Orkiestra oblicza: "Bet. Rozliczaj (wynik, wypłata) '→' Portfel. Committed (op_id) "i, jeśli wygrał," BonusWagered "→ możliwa konwersja bonusu na prawdziwe.
5. „BetSettled” → prognozy historii i bilansów, sprawozdawczość.
11) Niezmienne i polityka testowania
Najważniejsze niezmienne:- Suma wszystkich „LedgerEntry” w portfelu jest równa saldzie; brak negatywnych pozostałości.
- Nie można zaakceptować zakładu z aktywnym statusem KYC samodzielnego wykluczenia/zamrożonego.
- Zakład może tylko zmniejszyć i nie huśtawka „w minus”.
- Rozrachunek nie zmienia statusu już ukończonej stawki - tylko poprzez 'Void/Recalc' + kompensowanie transakcji.
- Testy na bazie własności portfela niezmienne i zakłady.
- Kontury chaosu: opóźnienia dostawcy, awarie PSP, redrives outbox/DLQ.
- Kontrola schematu: migracje zdarzeń, projekcje zasypek.
12) Telemetria i audyt
Metryki: p95/p99 na temat Zakładu/Rezerwy/Commit, udział awarii według limitów/ACC, szybkość DLQ, sukces przekierowania, prognozy opóźnień.
Odwzorowanie: spans „komanda → agregat → outbox → konsyumer → proyektsiya,” tags 'tenant _ id',' operation _ id', 'saga _ id'.
Audyt: niezmienny dziennik działań związanych z dziedziną porównywalny z wymogami regulacyjnymi.
13) System składowania (uproszczony)
Portfel:
wallet(id, tenant_id, currency, balance, reserved, version)
ledger(id, wallet_id, amount, type, operation_id, occurred_at)
holds(id, wallet_id, amount, operation_id, expires_at, status)
Zakład:
bet(id, tenant_id, player_id, amount, price, status, placed_at, settled_at, operation_id)
Bonus:
bonus_grant(id, tenant_id, player_id, amount, wager_left, status, expires_at)
Wersioning na agregatach („wersja”) chroni przed utratą aktualizacji podczas nagrywania konkurencyjnego.
14) Example Command API (pseudo)
http
POST /bets. place
{
"tenant_id":"T1",
"player_id":"P42",
"amount":"10. 00",
"price":"2. 1",
"operation_id":"op-uuid",
"context":{"game_id":"g777","channel":"web"}
}
→ 202 Accepted + BetPlaced
POST /wallets. reserve
{ "wallet_id":"W1", "amount":"10. 00", "operation_id":"op-uuid", "reason":"bet" }
→ 200 { "reserved_balance":"..." }
Wszystkie polecenia są z 'operation _ id' dla idempotencji, odpowiedzi są z' as _ of '/' wersja '.
15) Bezpieczeństwo i zgodność
RLS/ACL: wszystkie żądania - w kontekście 'lokator _ id', dostęp według roli.
Minimalizacja PII: oddzielenie zdarzeń domenowych od danych osobowych; maskowanie w DLQ/logach.
Raporty regulacyjne: projekcje z niezmiennymi podpisami hash w oknach czasowych.
16) Typowe błędy
Silna łączność między kontekstami (Portfel zna Bet/Bonus bezpośrednio).
Dual-write do różnych kontekstów bez sagi/outbox → niedopasowanie sald i statusów.
Brak poleceń i idempotencji konsumentów → duplikaty transakcji/obliczeń.
Przepływ umów dostawców do modelu domeny (trudniej jest migrować).
Jeden „olbrzymi” agregat (Gracz zawiera wszystkie) blokada →, niska przepustowość.
Nie ma oczywistych niezmienników - nie można ich sprawdzać i monitorować.
17) Szybkie przepisy kulinarne
Start: naprawić wszechobecny język i granice kontekstowe; dokumenty niezmienne.
Pieniądze: Portfel/Ledger - CP, wpisy kworum, TCC dla efektów zewnętrznych.
Zakłady: synchroniczny odbiór + asynchroniczne obliczenia, wszystko przez zdarzenia i outbox; Idempotencja jest wszędzie.
Bonusy: oddzielna jednostka z wyraźnym priorytetem odpisów i vager.
Integracje: zawsze poprzez systemy/wersje ACL +; brak „surowych” ładunków w rdzeniu.
Odczyty: projekcje/wyświetlacze na potrzeby produktu; świeżość SLA + „as _ of”.
Działanie: metryki niezmienników, DLQ/redrove playbooks, odbudować prezentacje.
18) Lista kontrolna przedsprzedaży
- Zdefiniowano ograniczone konteksty i ich umowy (polecenia/zdarzenia).
- Agregaty mają wyraźne niezmienne, wersioning i idempotentne polecenia.
- Transakcje pieniężne - poprzez TCC/ścisłą transakcję; włączony audyt.
- Integracje - poprzez ACL z testami wersji schematu i ewolucji.
- Zaimplementowane skrzynka odbiorcza/skrzynka odbiorcza, DLQ i bezpieczne redraw.
- Projekcje wdrażają świeżość SLA, istnieją wskaźniki opóźnienia/stalowości.
- Spełnione są kwoty/limity dla wielu najemców oraz rezydencja danych.
- Obserwowalność: śledzenie „komanda → sobytiye → proyektsiya”, wpisy przez niezmiennych.
- Dokumentacja: język domeny, schematy kontekstowe, playbooks incydentów.
Wnioski
DDD w rdzeniu iGaming to dyscyplina rozdzielenia złożoności: wyraźne granice kontekstu, agregaty z niezmiennikami, wydarzenia jako źródło prawdy, ACL dla integracji zewnętrznych i świadomych wyborów spójności. Takie podejście sprawia, że platforma jest skalowalna, niezawodna i zgodna z przepisami, przyspiesza rozwój funkcji i zmniejsza ryzyko operacyjne - nawet przy szybkim wzroście ruchu, geografii i linii produktów.