iGaming ядросындағы DDD
iGaming-платформа - бұл қаржы, ойын-сауық және комплаенс торабындағы күрделі домендік жүйе. DDD қиындықты ұстап тұруға көмектеседі: bounded contexts бөледі, ubiquitous language бекітеді, инварианттарды агрегаттармен қорғайды, сыбайлас жемқорлыққа қарсы қабаттар арқылы интеграцияны жеңілдетеді және домендік оқиғалар арқылы жүйенің мінез-құлқын ашық етеді.
1) Домен картасы және bounded contexts (стратегиялық дизайн)
Ұсынылатын декомпозиция:- Player/KYC Context - тіркеу, верификация, жауапты ойын лимиттері, KYC/AML мәртебелері.
- Wallet/Ledger Context - баланстар, резервтер, сымдар, мультивалюталық, курстар.
- Betting Context - ставкалар/тикеттер, жұп/нәтижелер, баға белгілеулер, есеп айырысу (settlement), күшін жою.
- Casino/Game Round Context - сессиялар, раундтар, арқалар, RTP-бақылау, мөлшерлемелер лимиттері.
- Bonus/Promo Context - бонустар, вагер, бонустық құралдар эквайрингі, анти-абьюз ережелері.
- Risk/Fraud Context - скоринг, мінез-құлық сигналдары, блоктау/тайм-ауттар триггерлері.
- Payments Context - депозиттер/қорытындылар, төлем шлюздерінің мәртебелері, chargeback-оқиғалар.
- Compliance/Reporting Context - реттеушілерге есептер, санкциялық тізімдер, аудит.
- Content/Provider Integration Context - ойын провайдерлерімен, каталогтармен, техникалық. мәртебелері.
- Analytics/Read Models - азық-түлік оқулары үшін проекциялар мен витриналар.
2) Ubiquitous language: терминдер өзегі
Player (Ойыншы), Session (Сессия), GameRound (Раунд), Bet/Ticket (Ставка),
Ledger Entry (Сым), Hold/Reserve (Резерв), Settlement (Есеп),
Bonus Credit / Bonus Balance, Wagering Requirement (Вейджер),
KYC Tier, Limit (депозит/сессия/жоғалту), Self-Exclusion,
Provider Game, RTP Window, Risk Flag, Compliance Case.
Бұл атаулар кодта, ДҚ-да, құжаттамада, тесттерде және интерфейстерде бірдей қолданылады.
3) Агрегаттар мен инварианттар (тактикалық дизайн)
3. 1 Wallet (Aggregate: `Wallet`)
Инварианттар:- Теңгерім минусқа кетпейді.
- Резерв + қол жетімді ≤ жалпы баланс.
- Сым атомарна мен іспеттес ('operation _ id' бойынша).
- `Wallet. Reserve(amount, reason, op_id)` → `WalletReserved`
- `Wallet. Commit(op_id)` → `WalletCommitted`
- `Wallet. Rollback(op_id)` → `WalletRolledBack`
Шекарасы: Wallet Bet/Bonus туралы білмейді; ол өткізгіштер мен резервтер операцияларына қызмет көрсетеді.
3. 2 Bet/Ticket (Aggregate: `Bet`)
Инварианттар:- Мөлшерлеме тек белсенді баға белгілеу терезесінде қабылдануы мүмкін; ойыншының/сессияның ≤ лимитінің сомасы.
- 'Settled' мәртебесінен кейін «аяқталды»; қайта есептеуге нақты аудитпен өтемдік операциялар (void/recalc) арқылы ғана жол беріледі.
- `Bet. Place(player_id, amount, price, op_id)` → `BetPlaced` (требует Wallet. Reserve)
- `Bet. Settle (outcome, payout) '→' BetSettled '(Wallet талап етеді. Commit/Release)
- `Bet. Void(reason)` → `BetVoided`
Шекарасы: Bet Walletке «кірмейді» - домендік командалар/оркестрлер арқылы жүгінеді.
3. 3 GameRound (Aggregate: `Round`)
Инварианттар:- Әрбір спин/раундтың бірегей 'round _ id' және ставканың/ұтыстың байланысты сомасы болады.
- RTP терезесі берілген шектен аспайды (провайдер деңгейінде + жергілікті ережелер).
- `Round. Started`, `Round. Staked`, `Round. Resulted`, `Round. Closed`.
3. 4 Bonus (Aggregate: `BonusGrant`)
Инварианттар:- Вейджер тек валидті айналымнан кішірейтіледі, бонусты есептен шығару дебетке кірмейді.
- Бонусты және нақты қаражатты басымдық ережесінсіз бір уақытта есептен шығару мүмкін емес.
- `BonusGranted`, `BonusWagered`, `BonusExpired`, `BonusConverted`.
4) Оркестрлер, сағалар және келісім
Синхронды (CP): мөлшерлемені қабылдау және қаражат резерві - бірыңғай жол: 'Bet. Place` → `Wallet. Reserve '(домендік команда/мерзімі ұзартылған оркестратор арқылы).
Асинхронды (EC): ставканы есептеу, бонустарды есептеу, талдау - оқиғалар арқылы + outbox.
TCC нұсқасы: 'TryReserve' (hold), 'Confirm' (commit), 'Cancel' (rollback).
Теңсіздік: барлық командалар 'operation _ id', консумерлер 'inbox' болады.
5) Сыбайлас жемқорлыққа қарсы топтар (ACL) және интеграция
Provider ACL: провайдерлік оқиғаларды «SpinResult», «BonusWin» ішкі 'Round-ға трансляциялау. Resulted`, `BonusWagered`. Схемалар мен нұсқалар - ACL ішінде.
PSP ACL: төлем мәртебесін қалыпқа келтіру, 'psp _ tx _ id' бойынша демпотенттілік, 'LedgerEntry' -ге аудару.
Compliance ACL: санкциялар/РЕР тізімдерімен ықпалдасу - сыртқы контексте; доменнің ішіне тек қалыпты 'ScreeningUpdated' кіреді.
Ереже: сыртқы сөздіктер/пішімдер ядроның ішіне «кірмейді».
6) Проекциялар және Read Models
Player Profile Read Model: KYC мәртебесі, лимиттер, белсенді бонустар, жаңа транзакциялар.
Balances Read Model: UI/маркетинг үшін жылдам оқу; оқиға көзі - 'Кошелек'.
Bet History Read Model: күндер/ойындар бойынша пагинация; көзі - 'BetPlaced/Settled'.
Compliance Reports: тенант/өңір бойынша материалданған көріністер.
Барлық проекциялар - нұсқасы және 'as _ of/freshness' болатын теңдессіз upsert '.
7) Мульти-тенант және мульти-өңір
Барлық негізгі мәнге 'tenant _ id' және (қажет болған жағдайда) 'region' жатады.
Деректер шекарасы: ойыншы, әмиян, ставкалар - «үй» аймағы; кросс-өңірлік тек агрегаттар/есептер.
Fairness/квоталар: команда/сек лимиттері және тенанттар бойынша редрайвтар.
Residency/комплаенс: дербес деректер мен сымдар аймақтан кетпейді.
8) Мәтінмәндер бойынша келісімділікті таңдау (PACELC)
Wallet/Ledger - Strong/CP: сызбалы сымдар, жазбалар кворумы.
Bet acceptance - синхронды растау (CP) + UI үшін жылдам Read Models.
Settlement/Bonus/Analytics - EC детерминирленген merge/өтемақымен.
KYC/Compliance - мәртебелер үшін EC болуы мүмкін, бірақ «бұғаттау» ережелері ілеспе қолданылады.
9) Домендік оқиғалар: келісімшарттар және нұсқа
Өрістердің ең кіші жиыны: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"
}
Ережелер:
- Back/forward-compat схемалары; 'schema _ version' арқылы эволюция.
- 'outbox' домендік өзгертулері бар транзакцияларда; backoff батчаларымен жариялау.
10) «Бонуспен ставка» ағынының үлгісі (сөз реттілігі)
1. `Bet. Place '(команда) → ойыншының лимиттерін және бонус ережелерін тексеру →' Wallet. Reserve(real+bonus_equiv, op_id)`
2. 'BetPlaced' (оқиға) → Read Model «Ашық ставкалар» жаңартады
3. Провайдер нәтижені жариялайды → ACL → 'Round. Resulted`
4. Оркестратор есептейді: 'Bet. Settle(outcome,payout)` → `Wallet. Commit (op_id) 'және, ұтқан кезде,' BonusWagered '→ бонустың нақты түрге ықтимал конверсиясы.
5. 'BetSettled' → тарих және баланс проекциялары, есептілік.
11) Инварианттар және тестілеу саясаты
Негізгі инварианттар:- Әмиян бойынша барлық 'LedgerEntry' жиынтығы теңгерімге тең; теріс қалдықтар жоқ.
- Белсенді self-exclusion/мұздатылған KYC-мәртебесінде мөлшерлемені қабылдауға болмайды.
- Вейджер кішірейіп, «минус» тербелмейді.
- Settlement қазірдің өзінде аяқталған мөлшерлеменің мәртебесін өзгертпейді - тек 'Void/Recalc' + компенсациялық сым арқылы.
- Property-based әмиян инварианттары мен мөлшерлемелер тесттері.
- Хаос контурлары: провайдердің кідіруі, PSP істен шығуы, outbox/DLQ редрайвтары.
- Схемаларды бақылау: оқиғаларды көшіру, backfill проекциялары.
12) Телеметрия және аудит
Метриктер: p95/p99 PlaceBet/Reserve/Commit, лимиттер бойынша істен шығу үлесі/АКҚ, DLQ rate, redrive success, lag проекциялары.
Трейсинг: ұйықтау «команда → агрегат → outbox → консьюмер → проекция», тегтер 'tenant _ id', 'operation _ id', 'saga _ id'.
Аудит: реттеуші талаптармен салыстырылатын өзгермейтін домендік әрекеттер журналы.
13) Сақтау схемасы (оңайлатылған)
Wallet:
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)
Bet:
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)
Агрегаттарда нұсқалау ('version') бәсекелес жазба кезінде lost update-тен қорғайды.
14) Командалардың API үлгісі (жалған)
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":"..." }
Барлық пәрмендер - с 'operation _ id', жауаптар - с 'as _ of '/' version'.
15) Қауіпсіздік және сәйкестік
RLS/ACL: барлық сұраулар - 'tenant _ id' контекстінде, рөлдер бойынша қатынау.
PII-азайту: домендік оқиғаларды дербес деректерден бөлу; DLQ/логтардағы бүркемелеу.
Реттеуші есептер: уақыт терезелері бойынша өзгермейтін хэш-қолтаңбалары бар проекциялар.
16) Типтік қателер
Контекстер арасындағы күшті байланыс (Wallet тікелей Bet/Bonus біледі).
Dual-write/outbox → теңгерімдер мен мәртебелерді келіспеу.
Командалар мен консьюмерлердің сәйкессіздігінің болмауы → сымдар/есептеулер дублдері.
Провайдерлік келісімшарттардың домендік модельге өтуі (қоныс аудару қиынырақ).
Бір «үлкен» агрегат (Player барлық қамтиды) → блоктау, төмен throughput.
Айқын инварианттар жоқ - оларды тексеру және мониторингілеу мүмкін емес.
17) Жылдам рецепттер
Бастау: Ubiquitous Language және контекстік шекараларды белгілеңіз; инварианттарды құжаттаңыз.
Ақша: Wallet/Ledger - CP, кворум жазбалары, сыртқы әсерлер үшін TCC.
Ставкалар: синхронды қабылдау + асинхронды есептеу, барлығы оқиғалар мен outbox арқылы; іспеттілік барлық жерде.
Бонустар: нақты есептен шығару басымдығы және вейджері бар жеке агрегат.
Интеграция: әрқашан ACL + схемалар/нұсқалар арқылы; ядрода ешқандай «шикізаттық» payload '.
Оқу: өнімнің қажеттілігіне арналған проекциялар/витриналар; Жаңалық SLA + 'as _ of'.
Операция жасау: инварианттар метрикасы, DLQ/редрайв плейбуктар, rebuild витриналар.
18) Азық-түлік алдындағы чек-парағы
- bounded contexts және олардың келісімшарттары (командалар/оқиғалар) анықталған.
- Агрегаттарда айқын инварианттар, нұсқалау және демпотенттік командалар бар.
- Ақша операциялары - ТСС/қатаң транзакциялық; аудит енгізілген.
- Интеграция - схемаларды және эволюция тесттерін нұсқалаумен ACL арқылы.
- outbox/inbox, DLQ және қауіпсіз редрайв енгізілді.
- Проекциялар SLA жаңаруын іске асырады, lag/staleness өлшемдері бар.
- Мульти-тенанттық квоталар/лимиттер және data residency сақталған.
- Бақылау: трейсинг «команда → оқиға → проекция», инварианттар бойынша алерттар.
- Құжаттама: домен тілі, контекстер диаграммалары, оқиғалар ойнатқыштары.
Қорытынды
iGaming ядросындағы DDD - бұл күрделілікті бөлудің тәртібі: нақты контекст шекаралары, инварианты бар агрегаттар, шындық көзі ретінде оқиғалар, сыртқы интеграциялар үшін ACL және саналы түрде келісушілікті таңдау. Мұндай тәсіл платформаны ауқымды, сенімді және реттеуге сәйкес етеді, фич әзірлеуді жеделдетеді және операциялық тәуекелдерді төмендетеді - тіпті трафиктің, географиялардың және өнім желісінің тез өсуі кезінде де.