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

4.5 KiB

Доставка личных сообщений

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 остаётся отдельным механизмом и продолжает работать.