у нас? если нужно, чтобы задания жили при перезапуске сервера?
Мне недавно такая идея пришла в голову: хранить стейт в самом процессе (например, Agent), а при остановке процесса (при перезапуске) сериализировать и выгружать, например, в базу данных. При запуске инициализировать из базы данных. Есть в этом смысл, или я чего-то не учитываю?
Потом придёт мысль сохранять только при изменении стейта. Потом ещё, ещё, и получится в итоге глючная самописная СУБД
"Потом придёт мысль сохранять только при изменении стейта." -> тут же перескочу на что-нибудь внешнее, но пока исходное условие в том, что это не требуется
Я так делал, работало сносно. Сейчас думаю, что все что касается консьюминга данных и того что нельзя терять - писать в персистентную очередь (eg rabbitmq). Получается проще, понятней и с масштабированием из коробки
Не очень понятно какая проблема решается. Если остановка штатная то зачем что-то сохранять а не дать процессу доработать? Если нештатная то всё равно потеряются данные.
спасибо за вопросы, они мне прояснили, что действительно не понятно, какая проблема решается. Изначально я думал о задаче, чтобы пре деплойменте не терялся стейт игр, которые ведутся на сайте (и в этом случае дать процессам доработать - не вариант). Но с другой стороны, если я останавливаю игру до перезапуска процесса, то... это неправильно). Игра должна продолжать идти на дополнительном node, а значит, эти ноды должны все равно шарить стейт, и какой-нибудь редис (или что-то подобное) в этом случае, в который стейт обновляется незамедлительно - единственный способ не прерывать игру. Так что моя идея оказывается все же неработающей (или как-минимум с более ограниченным применением, чем я подумал изначально).
Я думаю это просто blue green deployment решается
Это не blue-green называется, а rolling
Вообще, я могу тебя поздравить и поприветствовать в увлекательном мире персистентных акторов. Дисклеймер - мы делаем процессинг платежей, поэтому я могу немного серьезнее воспринимать тему, чем это осмысленно для тебя. Вариантов в целом немного, коммит в хранилище на каждом шаге, может быть с какими-то оптимизациями - типа, коммит не на каждом шаге плюс шардинг, чтобы вообще иметь возможность держать стейты в памяти. К библиотечным решениям(gen-server, gen-statem, Agent) привязываться я не рекомендую, они работают только в самых простых случаях, по мере усложнения кода начинают ставить палки в колёса, и сверх этого делают твой сервис stateful, а это сразу превращает горизонтальное масштабирование в изысканное развлечение для тонких ценителей. Мой последний подход к снаряду выглядит как очень минималистичная версия gen_statem, где и за персистенс, и за таймеры, и за выставление меты логгера отвечает общий код, а бизнесовый просто отдаёт ему команды на каждом шаге. В такой реализации сильно проще тестить бизнес-логику, потому что можно подсунуть фейковый интерпретатор. Особенно это хорошо, когда в логике начинается работа с таймерами - в версии с таймерами gen_statem до сих пор иногда валятся тесты из-за race conditions. Когда дойдёт до масштабирования, шардинг лучше делать по внешнему идентификаторы актора(типа, id чата, в котором идёт игра) и неплохо бы реализовывать на уровне роутинга входящих сообщений и внешними средствами, когда есть такая возможность. Отдельная очередь событий на каждый шард, и внутренние события, типа таймеров, должны так же проходить через неё, иначе можно попасть в грустную ситуацию.
у нас кстати часто рождается дизайн вида: * один модуль умеет слать сообщения, ставить таймеры, принимать сообщения и делать что-то грязное, но он не имеет права принимать решения * второй модуль имеет такое апи: f(InputCommand, State) -> {OutputCommands, State1} и он полностью pure, причем State условно json-ифицируем (по возможности).
да, на днях Sasa Juric в Thinking Elixir рассказывал про то, что он всегда делает похожее деление на interface и core. JSON, кстати, часто удобно заменить на :erlang.term_to_binary -- тогда, ценой читаемости, снимаются ограничения по структуре и добавляется скорость
Json-ифицируемость - не выбор самого способа сериализации, а скорее сама сериализируемость. Те то, что можно распечатаь, скопировать из консоли и засунуть обратно. Понятно, что это не жесткое правило, но вот с приходом именованных мониторов все стало еще удобнее
Обсуждают сегодня