3.2 KiB
3.2 KiB
Логика доставки почты (Signed Messages v2)
Что отправляет клиент
- Клиент формирует пару подписанных блоков с одинаковой базой (
baseKey): incoming— сообщение для получателя (targetLogin = toLogin).outgoing— копия для отправителя (targetLogin = fromLogin).- Пара отправляется методом
ReceiveOutcomingMessage(старое имяSendMessagePairоставлено для совместимости).
Что делает сервер при ReceiveOutcomingMessage
- Валидирует поля запроса (
incomingBlobB64,outgoingBlobB64). - Разбирает оба блока и проверяет, что это корректная пара.
- Проверяет пользователей и криптоподписи по каждому блоку.
- Пытается сохранить обе записи одной транзакцией:
- либо добавляются обе записи,
- либо при дубле/конфликте не добавляется ни одна.
- Если пара реально добавилась в БД, сервер запускает realtime-доставку в активные сессии целевых пользователей.
- Если это дубль, дальнейшая доставка не выполняется (повтор не разгоняется).
Почему допускаются дубли сети
- В модели с несколькими серверами возможны повторные пересылки одного и того же сообщения.
- Дедупликация делается на уровне БД по ключам записи.
- За счёт этого «шторм» затухает: сервер, который уже видел сообщение, больше его не разгоняет.
Будущая мультисерверная схема (цель)
- Клиент может отправить
ReceiveOutcomingMessageна любой из своих серверов. - Сервер-источник:
- сохраняет пару,
- рассылает исходящее по серверам пользователя A,
- рассылает входящее по серверам пользователя B.
- Остальные серверы повторяют тот же принцип, но благодаря дедупликации повторная пересылка быстро прекращается.
Важные текущие ограничения
- A) Реальной мультисерверности пока нет. Сейчас фактически предполагается один сервер на пользователя.
- B) Нет полноценного graceful shutdown для очереди пересылки. Возможен сценарий: запись уже сохранена в БД, но сервер перезагрузился до пересылки дальше. Это нужно доработать отдельно.