Files
SHiNE-server/docs/Personal_Messages/Доставка_и_синхронизация_DM.md
AidarKC 8a0275d962 Убрали старый sync и обновили bundle
Что сделано: вычистили неиспользуемый user-settings sync/DM sync хвост, сохранили сборку, обновили bundle.sh так, чтобы gradle-wrapper.jar всегда попадал в архив.

Проверено: compileJava и deploy на t2 (server + UI).
Не проверяли: полные интеграционные сценарии, ручные UI-флоу и продовый деплой.
2026-08-28 14:51:47 +04:00

85 lines
4.5 KiB
Markdown

# Доставка личных сообщений
## 1. Инвариант
У каждого пользователя действует ровно один сервер доступа: первый элемент
access_servers[0] в его Solana PDA.
Остальные элементы старой PDA, если они существуют, не участвуют в
маршрутизации и не являются fallback. UI позволяет только заменить текущий
сервер другим.
Межсерверной репликации личной переписки между серверами одного пользователя
нет. При смене сервера история автоматически не переносится.
## 2. Подписанные копии
Формат SHiNE_DM не меняется. Для сообщения клиент создаёт:
- входящую копию для получателя;
- исходящую копию для отправителя.
Сервер отправителя принимает пару через SendMessagePair, атомарно сохраняет её
и создаёт изменяемое состояние доставки.
## 3. Основной маршрут
1. UI отправителя вызывает SendMessagePair на своём access-сервере.
2. Сервер сохраняет исходящую копию отправителя и входящую копию, необходимую
для доставки и повторных попыток.
3. Сервер читает единственный маршрут получателя из
user_access_servers_current.
4. Если это другой физический сервер, он вызывает внутреннюю операцию
ReceiveIncomingMessage и передаёт только входящую копию.
5. Сервер получателя проверяет пользовательскую подпись, идемпотентно сохраняет
входящую копию и уведомляет активные сессии.
6. Успешное сохранение означает 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 остаётся отдельным
механизмом и продолжает работать.