-
GameId == уникальный game_id
-
HostId == уникальный server_id
-
ServerId == последовательность GameId (имеющих одинаковый HostId), предположительно образующих один «сервер»
-
Обычный хост — такой HostId, что в любой момент времени ему соответствует не более одной GameId (то есть на нём запущено не более одной factorio). При этом в ответе /get-games иногда для такого HostId может встречаться несколько GameId (причина: кеширование — если хост перестаёт отправлять heartbeat, то бекенд /get-games забывает его только через ~10 минут).
-
Мультихост — не обычный хост
- Для обычных хостов HostId и ServerId должны образовывать биекцию
- ServerId нам нужно задавать самим, будем использовать обычный счётчик, начиная с 1
- Будем хранить отдельно информацию о играх (GameId) и серверах (ServerId)
- Игры будем хранить просто как
HashMap<GameId, Game>
- ...
- Содержит prev_game_id
- Все строки одного типа (тип — например, «имя игрока», «описание игры», «название игры») будем хранить в одной большой строке, с разделителем — нулевым символом
- В структурах (Game, ...) вместо строк храним индекс начала части строки в большой строке
- При добавлении новой строки просто добавляем её в конец (не проверяя, существует ли она уже)
- Периодически (каждый раз после рестарта dyno, например, или мб чаще) удаляем дубликаты в больших строках
- Теги (массив строк) склеиваем в одну строку по разделителю \x02
- Моды: название и версию храним также как остальные строки, сам список модов храним просто как вектор пар
- перезапуск: игра с таким HostId исчезает и через несколько минут появляется снова (с новым game_id)
- перезапуск с наложением: как перезапуск, только после появления нового game_id старый тоже присутствует несколько минут (из-за особенностей кеширования)
- приостановка: как перезапуск, только разница может составлять часы/дни/недели
- потеря соединения: как перезапуск/приостановка, но game_id сохраняется
- все сценарии обычного хоста для любого подмножества игр, в любом временном порядке (в том числе одновременно)
- добавление новой игры/игр
- удаление игры/игр
Нас интересуют два события: появления или исчезновение game_id При появлении/исчезновении game_id добавляем HostId в список на «отложенное объединение» Через ~20 минут после последнего события появлении/исчезновении game_id производим объединение:
- объединяем два множества: {game_id, соответствующие HostId} для t=now и t=(now - 20minutes)
- не рассматриваем game_id, которые как были так и остались
- количество рассматриваемых game_id было и осталось не больше одного ⇒ всё однозначно
- иначе пытаемся объединять по game_name и game_host (в частности game_port)
Данный алгоритм не учитывает «приостановку». Поэтому дополнительно будем хранить для подходящих HostId последний ему соответствующий game_id. HostId является походящим если это обычный хост или если к моменту когда данный хост последний раз был онлайн ему соответствовал ≤1 game_id как минимум 24 часа.
В теории игры могут перемещаться между мультисерверами. Например, игры с названием factorioX.xzwq.net, где X ∈ [1, 9]
. Игры с X ∈ [4, 9]
образуют мультисервер (совпадает server_id), игры 1, 2 и 3 являются обычными (у каждой уникальный server_id). Хотя все игры хостятся в одном месте (в host_address
отличается только порт, хост совпадает). Однако это какой-то совсем крайний случай, поэтому не будем его рассматривать.
- Состояние сохраняется каждые 10 минут и также при получении сигнала SIGTERM
- Все состояния хранятся в папке
states-hourly/
, с именами видаH.bin.<compression>
, гдеH = floor(T / 3600)
, гдеT
— unix time в секундах - Причины такого формата хранения:
- просто применять алгоритм удаления ненужных бекапов (так как все бекапы уже пронумерованы)
- если приложение сломается, то матожидание длительности потерянного состояния равно
1час / 2 = 30минут
- Тип сжатия файла с состоянием:
- для последнего бекапа --- lz4 (самое быстрое, а у heroku всего 30 секунд timeout на завершение dyno)
- для бекапов --- xz (сжимает лучше всего)
- подробности в [various/analyze_compressions_methods]
- при старте dyno бекапы в формате lz4 будут конвертироваться в xz
Текущие сервера:
- Топ-10 серверов по числу игроков которые сейчас онлайн
- Топ-10 серверов по убыванию game_time_elapsed
Все сервера:
- Топ-10 серверов по максимальному числу игроков онлайн одновременно
- ...
- Топ-10 по человеко-часам за день/неделю/месяц/всё время
- табличка 7 на 24 с цветовой градацией — число игроков в соответствующее время (думаю даже более полезно для конкретного сервера, а не суммарно)
- такой же график числа игроков как на странице сервера, но для суммарного числа игроков на всех серверах
- график числа серверов с определённой версией (0.17/0.16) в зависимости от времени
- В промежутке 4-13 января 2020 зафиксировано примерно 5500 игр с именем "Fboys game" (с различным game_id). Каждая игра длилась примерно 2-3 минуты. Всё это время игры находились