Realtime на Rust: события вместо догадок

Живой интерфейс — это договор между сервером и клиентом о порядке, доставке и восстановлении событий.

Когда достаточно SSE

Server-Sent Events подходят для однонаправленных обновлений: статусы задач, уведомления, прогресс обработки. Браузер отправляет команды обычными HTTP-запросами, а изменения получает через EventSource. WebSocket нужен, когда действительно необходим двусторонний поток. Выбор протокола должен следовать сценарию продукта.

Конкурентность и память

Tokio выполняет асинхронные задачи, а каналы позволяют передавать события между обработчиками. Ограниченный broadcast-канал не хранит бесконечную историю. Медленный подписчик может пропустить сообщения: приложение должно либо восстановить состояние из БД, либо явно сообщить о разрыве. Rust помогает исключать многие ошибки памяти, но не выбирает стратегию доставки за разработчика.

Жизненный цикл соединения

Нужно закрывать EventSource при уходе со страницы, ограничивать количество подключений и отправлять keep-alive. Reverse proxy не должен буферизовать поток. Учитывайте таймауты и ограничение HTTP-соединений браузера. При повторном подключении используйте идентификаторы событий и источник восстановления, если продукт обещает доставку без потерь.

Честный демонстрационный поток

В лаборатории WERKIT событие сначала сохраняется в PostgreSQL, затем передаётся подключённым клиентам. Поток показывает новые события и не обещает восстановление пропущенных сообщений. Это сознательно ограниченный демосценарий. Для финансовых операций понадобятся дополнительный протокол подтверждения, устойчивый журнал и тесты с отказами.

Документация и дальнейшее чтение

Axum SSE ↗Tokio broadcast ↗MDN: server-sent events ↗
Посмотреть в лаборатории