Что сделано: вычистили неиспользуемый user-settings sync/DM sync хвост, сохранили сборку, обновили bundle.sh так, чтобы gradle-wrapper.jar всегда попадал в архив. Проверено: compileJava и deploy на t2 (server + UI). Не проверяли: полные интеграционные сценарии, ручные UI-флоу и продовый деплой.
4.5 KiB
Доставка личных сообщений
1. Инвариант
У каждого пользователя действует ровно один сервер доступа: первый элемент access_servers[0] в его Solana PDA.
Остальные элементы старой PDA, если они существуют, не участвуют в маршрутизации и не являются fallback. UI позволяет только заменить текущий сервер другим.
Межсерверной репликации личной переписки между серверами одного пользователя нет. При смене сервера история автоматически не переносится.
2. Подписанные копии
Формат SHiNE_DM не меняется. Для сообщения клиент создаёт:
- входящую копию для получателя;
- исходящую копию для отправителя.
Сервер отправителя принимает пару через SendMessagePair, атомарно сохраняет её и создаёт изменяемое состояние доставки.
3. Основной маршрут
- UI отправителя вызывает SendMessagePair на своём access-сервере.
- Сервер сохраняет исходящую копию отправителя и входящую копию, необходимую для доставки и повторных попыток.
- Сервер читает единственный маршрут получателя из user_access_servers_current.
- Если это другой физический сервер, он вызывает внутреннюю операцию ReceiveIncomingMessage и передаёт только входящую копию.
- Сервер получателя проверяет пользовательскую подпись, идемпотентно сохраняет входящую копию и уведомляет активные сессии.
- Успешное сохранение означает delivered.
ReceiveIncomingMessage не является синхронизацией двух серверов одного пользователя. Это основная доставка между серверами разных пользователей.
4. Повторные попытки
Попытки привязаны ко времени первоначального принятия:
- сразу;
- через 30 секунд;
- через 5 минут;
- через 25 минут;
- через 1 час.
Перед каждой попыткой заново читается первый актуальный access-сервер получателя. После финальной неудачи состояние становится failed.
Второй сервер отправителя не опрашивается, полная пара ему не передаётся.
5. Состояния
- accepted — пара сохранена сервером отправителя;
- delivered — входящая копия сохранена единственным сервером получателя;
- failed — финальная попытка завершилась неудачей;
- read-receipt — отдельное подписанное DM-событие.
Подписанные DM-контейнеры остаются криптографическими фактами. Сетевое deliveryState остаётся изменяемой серверной метаданной.
6. Удаления
DeleteMessage и DeleteConversation доставляют подписанный tombstone только на единственные access-серверы обеих сторон. Повторное применение идемпотентно.
7. Удалённая репликация
После перехода на один сервер доступа удалены:
- ReceiveOutcomingMessage;
- DmSyncBatch;
- GetDmDeliveryStatus;
- dm_sync_outbox;
- dm_sync_peer_state;
- ACK-флаги synced;
- периодический DM-backfill между access-серверами.
Блокчейн-синхронизация через server-PDA sync_servers остаётся отдельным механизмом и продолжает работать.