WebSocket сохраняет порядок кадров внутри одного соединения, но приложение все равно может показать события не по порядку. Причина появляется при нескольких producers, параллельной обработке, reconnect, повторной доставке из очереди или объединении событий разных сущностей.
Не пытайтесь исправить интерфейс искусственной задержкой каждого сообщения. Нужен явный порядок на уровне бизнес-событий: sequence, version или серверное время, а также правила обработки пропусков и повторов.
Определите место перестановки
Сравните порядок создания, публикации, получения и применения одного набора событий.
- Событие обновления применяется раньше создания.
- После reconnect старое состояние затирает новое.
- Порядок ломается только при высокой нагрузке.
- Два вкладки показывают разные конечные значения.
Почему возникает проблема
Сетевой порядок не гарантирует последовательность между разными соединениями и асинхронными задачами.
- Несколько worker публикуют события одной сущности параллельно.
- Async handler завершает тяжелое сообщение позже следующего.
- После reconnect клиент получает snapshot и buffered events в неверном порядке.
- События не имеют version или sequence.
- Повторная доставка применяется как новая операция.
Пошаговая диагностика
Добавьте correlation ID, entity ID и sequence без записи чувствительной нагрузки.
- Сопоставьте момент записи в базе и публикации события.
- Проверьте partition или routing key очереди.
- Зафиксируйте receive order и completion order обработчика.
- Повторите disconnect и reconnect во время обновления.
- Найдите дубли и пропуски sequence для одной сущности.
Версионируйте состояние сущности
Клиент должен понимать, является ли событие новым, повторным или устаревшим.
- Каждое изменение получает монотонную version для entity.
- Клиент игнорирует version ниже уже примененной.
- Пропуск версии запускает запрос актуального snapshot.
- Повтор события не меняет состояние второй раз.
Как исправить проблему
Согласуйте порядок публикации и правила восстановления клиента.
- Публикуйте событие после подтвержденной записи в базе.
- Сериализуйте события одной сущности через partition или lock.
- Добавьте sequence, version и event ID.
- Применяйте клиентские изменения последовательно для entity.
- После reconnect получайте snapshot с границей событий.
Как проверить результат
- Новые версии никогда не затираются старыми.
- Повторное событие безопасно игнорируется.
- После reconnect интерфейс приходит к состоянию базы.
- Нагрузка и несколько worker не нарушают порядок entity.
Типичные ошибки
- Сортировать только по клиентскому времени.
- Полагаться на порядок разных WebSocket-соединений.
- Запускать async handlers без последовательного применения.
- Считать reconnect продолжением прежнего потока без границы.
Как предотвратить повторение
- Добавьте version и event ID в контракт.
- Тестируйте reorder, duplicate и missing events.
- Маршрутизируйте одну сущность в одну partition.
- Мониторьте пропуски sequence.
Когда нужна помощь
Если WebSocket-события меняют состояние в неверном порядке, я прослежу очередь, producers, reconnect и клиентский handler, добавлю sequence и надежное восстановление без случайных задержек.