Соединение и завершённое действие — разные состояния
WebSocket позволяет обмениваться данными в обе стороны через длительное соединение. Но прикладной смысл сообщения задаёт сам сервис. Отправлено, получено сервером, сохранено и показано собеседнику — разные этапы, которые нельзя обозначать одним неясным статусом. Например, Socket.IO сохраняет порядок доставленных событий, но по умолчанию не гарантирует доставку каждого события при разрыве. Автоматическое переподключение не восстанавливает всю историю приложения само по себе. Если важны пропущенные сообщения, нужны отдельные правила хранения и получения недостающих данных.
Повтор должен иметь узнаваемую идентичность
Представим, что сервер сохранил сообщение, но подтверждение потерялось. Клиент не знает, завершилось ли действие, и отправляет его снова. Если каждую попытку считать новым сообщением, появится дубликат. Поэтому логическому действию заранее назначают устойчивый идентификатор. Сервер связывает идентификатор с пользователем и результатом обработки. Повтор той же операции должен возвращать согласованный результат, не создавая ещё одну запись. Проверку и сохранение проектируют так, чтобы одновременно пришедшие попытки не обошли защиту. Подтверждение важно выдавать после того этапа, который оно действительно обещает.
Быстрый обмен не отменяет ограничения нагрузки
Node.js выполняет обработчики JavaScript через цикл событий. Длительная синхронная работа в таком обработчике задерживает обслуживание других соединений. Объявление функции асинхронной само по себе не переносит тяжёлые вычисления на отдельный исполнительный ресурс. Ограничивайте размер сообщений и частоту событий, продумывайте поведение при переполнении очереди. Медленный получатель не должен заставлять сервер бесконечно накапливать данные. Для разных событий допустимы разные решения: промежуточное положение указателя можно заменить последним, а пользовательское сообщение требует иной политики сохранения.
Права и восстановление проверяют вместе
Подключённый клиент не получает автоматически право читать любую комнату или отправлять любое событие. Сервер проверяет личность, доступ к конкретному ресурсу и структуру входных данных. Нельзя доверять переданному клиентом идентификатору пользователя как доказательству полномочий. После переподключения клиент может сообщить, до какого события дошёл. Сервер возвращает только разрешённые ему данные и учитывает срок хранения истории. В журнале полезно различать разрыв, отказ по правам, повтор и успешную обработку. Проверка таких сценариев важнее демонстрации обмена двумя сообщениями в стабильной локальной сети.
Попробуйте на практике
Спроектируйте на бумаге обработку одного сообщения в вымышленном чате, не запуская сервер и не передавая реальные пользовательские данные.
- Опишите четыре состояния: создано клиентом, принято сервером, сохранено и показано получателю. Укажите, какой статус видит отправитель на каждом этапе.
- Назначьте сообщению условный идентификатор и свяжите его с вымышленным отправителем. Запишите результат, который сервер вернёт при повторе.
- Разыграйте разрыв после сохранения, но до подтверждения. Проверьте, что повтор не создаёт вторую запись и не выдаёт преждевременный успех.
- Добавьте правила для слишком большого сообщения, частых отправок и запроса чужой комнаты. Определите отказ без раскрытия чужого содержимого.
- Опишите восстановление истории по последнему известному событию и случай, когда нужные данные уже недоступны. Не обещайте восстановление без предусмотренного хранения.
Как проверить результат. Схема различает транспорт и результат обработки, предотвращает дубликат при повторе и проверяет доступ. Переподключение не объявляется доказательством доставки всех сообщений.
Частые вопросы
Достаточно ли включить автоматическое переподключение?
Нет. Оно восстанавливает связь, но правила хранения, подтверждения и получения пропущенных событий относятся к логике приложения.
Любая функция с async не блокирует остальные соединения?
Нет. Длительные синхронные вычисления внутри неё всё равно могут занимать цикл событий. Характер работы нужно оценивать отдельно от синтаксиса функции.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.