Почта v2: ReceiveOutcomingMessage без авторизации и атомарная вставка пары

This commit is contained in:
AidarKC
2026-05-02 16:46:22 +03:00
parent e73328461e
commit b7e6cf7437
6 changed files with 123 additions and 18 deletions
@@ -0,0 +1,34 @@
# Логика доставки почты (Signed Messages v2)
## Что отправляет клиент
- Клиент формирует **пару подписанных блоков** с одинаковой базой (`baseKey`):
- `incoming` — сообщение для получателя (`targetLogin = toLogin`).
- `outgoing` — копия для отправителя (`targetLogin = fromLogin`).
- Пара отправляется методом `ReceiveOutcomingMessage` (старое имя `SendMessagePair` оставлено для совместимости).
## Что делает сервер при `ReceiveOutcomingMessage`
1. Валидирует поля запроса (`incomingBlobB64`, `outgoingBlobB64`).
2. Разбирает оба блока и проверяет, что это корректная пара.
3. Проверяет пользователей и криптоподписи по каждому блоку.
4. Пытается сохранить обе записи **одной транзакцией**:
- либо добавляются **обе** записи,
- либо при дубле/конфликте не добавляется **ни одна**.
5. Если пара реально добавилась в БД, сервер запускает realtime-доставку в активные сессии целевых пользователей.
6. Если это дубль, дальнейшая доставка не выполняется (повтор не разгоняется).
## Почему допускаются дубли сети
- В модели с несколькими серверами возможны повторные пересылки одного и того же сообщения.
- Дедупликация делается на уровне БД по ключам записи.
- За счёт этого «шторм» затухает: сервер, который уже видел сообщение, больше его не разгоняет.
## Будущая мультисерверная схема (цель)
- Клиент может отправить `ReceiveOutcomingMessage` на любой из своих серверов.
- Сервер-источник:
- сохраняет пару,
- рассылает исходящее по серверам пользователя A,
- рассылает входящее по серверам пользователя B.
- Остальные серверы повторяют тот же принцип, но благодаря дедупликации повторная пересылка быстро прекращается.
## Важные текущие ограничения
- **A) Реальной мультисерверности пока нет.** Сейчас фактически предполагается один сервер на пользователя.
- **B) Нет полноценного graceful shutdown для очереди пересылки.** Возможен сценарий: запись уже сохранена в БД, но сервер перезагрузился до пересылки дальше. Это нужно доработать отдельно.