Overwatch Tournaments Dev нужны функциональные cookie, чтобы сохранять вход и язык интерфейса. Аналитические cookie необязательны и только показывают, как используются страницы, — подробнее в политике конфиденциальности.

Перейти к содержимому
тест

Postgres-схемы

СхемаДоменКлючевые таблицыВладелец
authАутентификация и RBACuser, refresh_token, oauth_connections, api_key, roles, permissions, user_roles, role_permissions, user_permission_denyauth-service
playersИдентичность игрокаuser, social_account, social_account_visibility, user_merge_auditapp-service
publicВоркспейсы, сетки дивизионов, инфраworkspace, workspace_member, division_grid*, settings, event_outboxapp-service
tournamentСтруктура турнира и сеткаtournament, stage, stage_item, team, player, standing, encounter, encounter_link, challonge_*, computation_jobtournament-service
overwatchСправочник игрыhero, map, gamemodeapp / parser
overwatch_rankТелеметрия рангов OWrank_snapshot, battle_tag_state, fetch_logparser-service
matchesРазобранные матч-логиmatch, statistics, kill_feed, assists, mv_hero_global_stats (MV)parser-service
balancerРегистрация и балансировкаregistration*, balance*, team*, tournament_config, draft_*balancer-service
achievementsДвижок достиженийrule, evaluation_result, override, evaluation_runparser / app
analyticsАналитика и MLtournament, shifts, performance, standings_distribution, match_quality, ml_*, job, …analytics-service
log_processingЗагрузка/парсинг логовrecord, discord_channelparser / discord
realtimeЖурнал realtime-событийworkspace_eventgateway (Go)
subscriptionsПодписки и энтайтлментыprovider_config, requirement, entitlement, check_logtournament / parser

Общие хабы

public.workspace
арендатор (мультитенантность). Почти всё скоупится по workspace_id.
players.user
доменная идентичность игрока (может существовать без аккаунта — «shadow player» из логов/CSV).
auth.user
учётная запись для входа; линк к players.user1:0..1.
workspace_member
якорь принадлежности игрока к воркспейсу (уникальность по workspace_id + player_id); на него по workspace_member_id ссылаются ростер (tournament.player), регистрации (balancer.registration), драфт (draft_team/draft_player/draft_pick) и достижения (evaluation_result/override). Денормализованной роли нет — роль выводится из RBAC.
tournament.tournament
турнир; корень для стадий, команд, матчей, регистраций, аналитики.
overwatch.hero
герой; на него ссылаются статистика, топ-герои регистрации, достижения.

Карта доменов

Какие схемы на что ссылаются. Пунктирное ребро — связь «1:0..1» между auth и players.

100%
Рендер диаграммы…

История изменений схемы

Документ актуализирован под финальное состояние (Alembic head — wsreq0002).

Identity/workspace-рефактор
players.user.auth_user_id (unique nullable; NULL = shadow-player) — линк 1:0..1 к auth.user. public.workspace_member ключуется на player_id (FK → players.user) с уникальностью (workspace_id, player_id); денормализованная роль убрана. На workspace_member_id теперь якорятся balancer.registration (dbarch02), tournament.player (iwrefac07, NOT NULL), draft_team/draft_player/draft_pick (dbarch03) и achievements.evaluation_result/override.
Challonge-нормализация (dbarch04 + dbarch04b)
Удалены tournament.tournament.challonge_id/challonge_slug, tournament.stage.challonge_id/challonge_slug, tournament.encounter.challonge_id и таблица tournament.challonge_team. Источник правды — challonge_source + challonge_participant_mapping + challonge_match_mapping + challonge_sync_log. Таблица tournament.group (вместе со своими challonge_id/challonge_slug) снесена миграцией dropgrp01; группа Challonge связывается со стадией только через stage.settings_json.challonge_group_id, по которому и роутится match.group_id. Одноимённые поля ответов API живы, но ВЫВОДЯТСЯ из challonge_source/challonge_match_mapping резолверами shared/services/challonge_refs.py — сериализатор, который их не прокинул, отдаёт тихий null.
JSON-нормализация (dbarch05)
map_veto_config.map_pool_ids (JSON) → дочерняя map_veto_config_map; veto_sequence_json остался JSON.
Драфт без ролей и рангов (draftreg1)
Роли и ранги в драфте не хранятся вообще. dbarch03 вынес их из JSON в balancer.draft_player_role + draft_player_role_hero, а draftreg1 снёс обе таблицы вместе с колонками draft_player.primary_role/sub_role/is_flex/division_number/rank_value/battle_tag/additional_info. Осталась ссылка draft_player.registration_id → balancer.registration (NOT NULL, RESTRICT, UK (session_id, registration_id) вместо uq_draft_player_session_member), а роли и ранги резолвятся на чтении из balancer.registration_role движком shared.services.roster. RESTRICT намеренно: заявка удаляется мягко, поэтому жёсткое удаление — это попытка стереть строку, от которой зависит драфт, и она отклоняется, а не рушит историю. Единственная сохранённая производная — draft_pick.target_role/target_rank_value, замороженные как исторический факт о состоявшемся пике.
Predictions (dbarch06)
analytics.predictions (v1) удалена; analytics.standings_distribution (v2) — единственный источник прогноза мест.
Гигиена индексов/FK (dbarch01)
Индексы на auth.user_roles/auth.role_permissions; новые FK: achievements.evaluation_result.run_id → evaluation_run, players.user_merge_audit.source_user_id/target_user_id → players.user, auth.user_permission_deny.created_by → auth.user; перенос типа encounterstatus publictournament; частичный unique-индекс на players.social_account для NULL-хендлов.
Правило подписки на воркспейсе (wsreq0001 + wsreq0002)
Новая таблица subscriptions.requirement (workspace_id, name, requirement_json, is_default; UK (workspace_id, name) плюс частичный unique на дефолтную строку) — единственный источник правила допуска, общего для всех турниров воркспейса. Пара expand/contract, порядок обязателен: wsreq0001 создаёт таблицу и бэкфиллит её из форм (до раскатки кода, потому что новый load_requirement селектит эту таблицу), затем wsreq0002 удаляет столбец с правилом из balancer.registration_form (после раскатки, потому что старая ORM всё ещё маппит его и SQLAlchemy эмитит его в каждом SELECT). Бэкфилл не выбирает правило за организатора: если у воркспейса больше одного различного правила, wsreq0001 падает и откатывается. Тумблер require_subscription остался на форме — он и есть пер-турнирное решение.

Заметки по чтению диаграмм

Мультитенантность
Почти каждая бизнес-таблица несёт workspace_id (напрямую или транзитивно через tournament/workspace_member). Глобальные сущности (роль/деней/сетка/статус) допускают workspace_id = NULL.
Двойная идентичность
auth.user (вход) и players.user (игрок) — разные таблицы, связь 1:0..1. Ростер (tournament.player), регистрации (balancer.registration), драфт (draft_*) и достижения (evaluation_result/override) якорятся на workspace_member (= уникальность workspace_id + player_id), что и есть суть identity/workspace-рефактора. Денормализованной роли на workspace_member нет — роль выводится из RBAC.
Legacy не осталось
tournament.group снесена миграцией dropgrp01 (группы = stage_item типа GROUP). achievements.achievement/achievements.user и analytics.predictions (v1) — удалены (см. «История изменений схемы»).
Циклические FK
draft_session.current_pick_id ↔ draft_pick.session_id (создаётся с use_alter); division_grid_version.created_from_version_id и tournament.player.related_player_id — само-ссылки.
Enum encounterstatus
Тип перенесён из схемы public в tournament (dbarch01); хранит имя члена (COMPLETED/PENDING/OPEN), не .value.
mv_hero_global_stats
materialized view (не в диаграммах как таблица): глобальные рекорды по (hero, stat), обновляется вне транзакций.