GH GambleHub

Движок каталога контента

Движок каталога — это ядро витрин игр и промо-подборок на фронте: он собирает и нормализует метаданные от провайдеров (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&region=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-метриками и строгий комплаенс превращают каталог в устойчивый и измеримый продуктовый рычаг роста — без сюрпризов в продакшене и без компромиссов с регуляторами.

Contact

Свяжитесь с нами

Обращайтесь по любым вопросам или за поддержкой.Мы всегда готовы помочь!

Начать интеграцию

Email — обязателен. Telegram или WhatsApp — по желанию.

Ваше имя необязательно
Email необязательно
Тема необязательно
Сообщение необязательно
Telegram необязательно
@
Если укажете Telegram — мы ответим и там, в дополнение к Email.
WhatsApp необязательно
Формат: +код страны и номер (например, +380XXXXXXXXX).

Нажимая кнопку, вы соглашаетесь на обработку данных.