Рушій каталогу контенту
Рушій каталогу - це ядро вітрин ігор і промо-добірок на фронті: він збирає і нормалізує метадані від провайдерів (RGS), забезпечує пошук/фільтри/ранжування, застосовує правила доступності по юрисдикціях і брендам, підмішує персоналізацію і промо-плейсменти, а потім віддає швидкі відповіді через API з передбачуваним SLO.
1) Цілі та принципи
Швидкі читання: p95 ≤ 100-150 мс на запит каталогу/пошуку.
Правда і свіжість: гарантована актуальність ключових атрибутів (доступність, джекпоти, провайдерські статуси).
Гнучкість: редакторські колекції та промо-слоти без релізів.
Відповідність: правила гео/віку/контенту, ліцензії, обмеження відповідальної гри.
Мульти-тенант/регіон: ізоляція брендів і дотримання data residency.
Спостережуваність: метрики якості видачі, A/B, конверсія в гру/ставку.
2) Доменна модель (мінімум)
Сутності:- Game - гра/продукт провайдера.
- Provider - RGS/студія.
- Variant - варіанти однієї гри (волатильність, лінії, ліміти, сервер).
- Collection - редакторська/автоматична добірка (наприклад, «Новинки», «Джекпоти»).
- Placement - закріплена позиція/банер/тайл на сторінці/в слоті.
- Capability/Feature - атрибути гри (free spins, buy feature, джекпот).
- JurisdictionRule - правила доступності/обмежень.
- Signals - поведінкові/операційні сигнали (популярність, CTR, revenue).
- Asset - медіа (іконки, постери, демо-відео) з варіантами для пристроїв/щільностей.
Ключі: 'game _ id'( стабільний внутрішній, не дорівнює provider_game_id),'tenant _ id','region','locale'.
3) Ingest і нормалізація
Конвеєр:1. Source Adapters (пулери): інтеграції з RGS/студіями (каталоги, фічі, RTP, теги).
2. Sanitize & Map: маппінг зовнішніх полів в єдиний словник (ACL), валідація і дедуплікація.
3. Enrich: локалізації, категорії, семантичні теги, рейтинги вікових обмежень.
4. Moderate: контент-прапори (NSFW/релігійні символи/чутливі теми) по ринках.
5. Publish: події'GameUpserted/ProviderStatusChanged'→ проекції каталогу.
Ідемпотентність: всі повідомлення з'source _ id'+'version _ ts'; повтор обробляється без побічних ефектів.
Схема еволюції: 'schema _ version'в адаптерах + міграції мапперів.
4) Нормалізована схема (спрощено)
json
{
"game_id": "g_3f92",
"tenant_id": "brand_eu",
"provider": { "id": "pr_evolution", "name": "Evolution" },
"title": { "en": "Lightning Roulette", "de": "Lightning Roulette" },
"capabilities": ["live","roulette","multiplier","bonus"],
"rtp": 97.3,
"volatility": "high",
"limits": { "min": 0.1, "max": 1000.0, "currency": "EUR" },
"jurisdiction": {
"allowed": ["MT","EE","DE"],
"blocked": ["NL","BE"],
"age_rating": 21
},
"assets": {
"tile": { "1x":"...", "2x":"..." },
"poster": { "web":"...", "mobile":"..." }
},
"tags": ["new","jackpot"],
"release_date": "2025-09-12",
"status": "active",
"variants": [{ "id":"v1","server":"eu-central-1","rtp":97.3 }]
}
5) Пошук, фільтри, фасети
Індекси: повнотекст за назвою/синонімами, фасети за'provider','capabilities','volatility','rtp _ bucket','tags'.
Фільтри: юрисдикція/регіон/мова/пристрій/вік, тільки активні/сертифіковані.
Синоніми/стемінг: карта призначених для користувача термінів («книжки», «фрукти», «кулі»).
Помилки: tolerant search (edit distance ≤1 -2) з обмеженням по довжині.
6) Ранжування: сигнали і формула
Сигнали (приклад):- Freshness (час з релізу).
- Popularity (запуски/година, унікальні гравці).
- Quality (CTR з каталогу в гру, утримання 1/7 день).
- Business (маркетингові бусти, угоди, промо-слоти).
- Compliance (м'які зниження для чутливого контенту, якщо потрібно).
- Player-fit (сумісність профілю/уподобань).
score = w1freshness + w2popularity + w3ctr + w4player_fit + w5boost
Ваги управляються конфігурацією/експериментами; всі сигнали нормалізовані на [0; 1].
7) Персоналізація
Коротка пам'ять: останні запуски і жанри, RYW - користувач відразу бачить свіжі дії.
Довга пам'ять: ембеддинги ігор і профілю гравця (ігрові жанри/волатильність/сесії).
Безпека: персоналізація ніколи не порушує юрисдикційні/вікові правила.
Fallback: якщо сигналів мало - нейтральне ранжування + редакторські колекції.
8) Колекції та промо-плейсменти
Колекції:- Авто: правило/запит (напр.,'capabilities contains'jackpot'AND release_date> = NOW () -30d').
- Редакторські: ручний список з порядком і термінами.
- Плейсменти: закріплені позиції на сторінках (hero, row-1-slot-3), A/B, таргетинг за сегментами/юрисдикціями.
- Терміни та пріоритети: 'starts _ at/ends _ at', пріоритет колізій, прев'ю перед публікацією.
9) Комплаєнс і політика доступності
Гео/юрисдикція: білі/чорні списки країн/регіонів, перевірка ліцензій/сертифікатів.
Віковий рейтинг: мінімальний вік, попередження, приховування для несумісних ринків.
Тематика/символіка: прапори чутливого контенту по країнах (релігія, алкоголь і т.п.).
Відповідальна гра: приховування/зниження для гравців з лімітами/тайм-аутом.
Аудит: незмінний лог змін доступності з причинами.
10) Мульти-тенант і мульти-регіон
Всі дані позначені'tenant _ id'і'region'.
Ізоляція: кворуми/сховища по регіонах; крос-регіональні проекції - тільки агрегати.
Fairness: квоти на ingest/публікації per tenant, щоб «галасливий» бренд не затримував інших.
11) Архітектурний контур
Write-ядро каталогу (CP): нормалізація + транзакційний outbox подій.
Проекції/Read Models (EC): індекси пошуку, матеріалізовані колекції, лічильники популярності.
- Edge/CDN для «холодних» сторінок/зображень.
- In-memory кеші для гарячих запитів (key = фільтри + сторінка + tenant + region).
- Фічефлагі: прокатка правил ранжування/колекцій без релізу.
12) API (REST/GraphQL, приклади)
REST
GET /v1/catalog?tenant=brand_eu®ion=EE&locale=ru
&filter=jackpot,true&sort=score_desc&page=1&size=24
→ 200 { items:[...], facets:{...}, as_of:"2025-10-31T12:10:02Z" }
GraphQL (фрагмент)
graphql query Catalog($tenant:String!,$region:String!,$q:String,$filters:Filters){
catalog(tenant:$tenant, region:$region, q:$q, filters:$filters){
items { gameId title provider { name } score badges assets { tile } }
facets { providers { key,count } capabilities { key,count } }
freshnessMs
}
}
Контракти:
- Завжди повертайте'as _ of/freshnessMs', пейджинг, фасети.
- Для персоналізації - маркер сесії (RYW) без PII.
13) Сигнали і потік даних
Популярність: інкременти при запуску ігор → хвилинні бакети → агрегати в проекції.
CTR/конверсія: лічильники кліків/запусків на плейсментах/колекціях.
Операційні статуси: health провайдерів (RGS), джекпоти/ліміти (стрім подій).
Маркетинг-бусти: тимчасові коефіцієнти для ігор/категорій/постачальників.
14) Спостережуваність і SLO
Метрики каталогу:- `catalog_p95_ms`, `catalog_p99_ms`, `error_rate`.
- 'index _ freshness _ ms'( проектна затримка),'ingest _ lag _ ms'.
- 'ctr','click-to-launch','collection _ coverage'(% видачі з колекцій).
- `lift_ctr`, `lift_conversion`, «explore vs exploit» доля.
- % коректно застосованих гео/вікових правил, число блоків/год.
Алерти: зростання'ingest _ lag _ ms', падіння CTR на ключових колекціях, деградація провайдера (мітки у видачі).
15) Продуктивність і кешування
Стратегія: гарячі запити - кеш на 30-120 з ключем за фільтрами; персональні блоки - короткий TTL (10-30 с) або без кешу.
Інвалідація: за подіями'GameUpserted/AvailabilityChanged/PlacementUpdated'.
Пагінація: стабільні курсори, щоб не «скакали» картки при оновленні сигналів.
16) Робота з медіа
Рендер-профілі: розміри/щільності для web/mobile/TV.
Оптимізація: WebP/AVIF, lazy-load, sprite/atlas для плиток.
Контент-безпека: сканування, водяні знаки, заборона inline-PII.
17) Тестування
Contract/Schema tests для адаптерів і API.
Relevancy tests: золоті набори запитів → очікувані результати/порядок.
Персоналізація: offline AUC/NDCG + online A/B з guardrail-метриками (час в грі, депозити, RG-сигнали).
Chaos: деградації провайдерів, сплески ingest, затримки індексації.
18) Плейбуки (runbooks)
1. Лаг індексу> SLO: зупинити вторинні колекції, підвищити пріоритет ingest, тимчасово спростити ранжування.
2. Провайдер «червоний»: знизити/приховати його ігри, підняти альтернативні колекції.
3. Стрибок помилок API: перевірити кеш/бекенд, включити захисні таймаути, зменшити розмір сторінок.
4. Некоректні доступності: відкотити останнє правило, включити «білий список» критичних ринків, провести аудит змін.
5. Реліз ранжування: канарний rollout (5% → 25% → 50% → 100%), відкат по CTR/конверсії.
19) Типові помилки
Змішування зовнішніх схем провайдерів з внутрішньою моделлю (відсутність ACL).
Відсутність'as _ of/freshness'→ суперечки про «застарілому» каталозі.
Персоналізація, що порушує юрисдикційні правила.
Єдина «магічна» формула ранжування без розкладання сигналів і A/B.
Великі сторінки без кешування і курсорів → p99 «стріляють».
Dual-write в індекс і OLTP замість подій + проекцій.
20) Чек-лист перед продом
- Нормалізований словник полів і ACL для всіх провайдерів.
- Ідемпотентний ingest, outbox/inbox, DLQ і редрайв.
- Проекції каталогу та індекси пошуку з SLO свіжості.
- Ранжування з керованими вагами, розкладання сигналів і A/B.
- Комплаєнс-правила (гео/вік/тематика) і аудит змін.
- Мульти-тенант/регіон: ізоляція даних, fairness, residency.
- API з'as _ of', фасетами, курсорами; кеш та інвалідація щодо подій.
- Метрики p95/p99, ingest/індексація, CTR/конверсія; алерти.
- Плейбуки інцидентів; канарські релізи і фічефлаги.
- Тести релевантності, контрактів, хаосу і персоналізації.
Висновок
Рушій каталогу - це «пошуковик + правилова система + вітрина» над ігровим контентом. Сильний ACL, нормалізовані дані, проекції для швидких читань, прозорі сигнали ранжування, персоналізація з guardrail-метриками і строгий комплаєнс перетворюють каталог в стійкий і вимірний продуктовий важіль зростання - без сюрпризів в продакшені і без компромісів з регуляторами.