Зафиксировать успешную синхронизацию на тестовом сервере

This commit is contained in:
AidarKC 2026-06-26 17:46:34 +04:00
parent 44a1ba01f3
commit 87eec7e5c9
9 changed files with 52 additions and 96 deletions

View File

@ -1,5 +1,13 @@
# История изменений документации блокчейна
# 2026-06-26 17:45:18 +0400
- Базовый коммит-ориентир: `44a1ba0`.
- На `t.shineup.me` подтверждена рабочая схема startup sync и full-resync:
- после рестарта сервер добивает `BlockchainTmpRecovery` и `BlockchainResyncRecovery`;
- `aidartest-001` успешно подтягивается с `shineup.me`;
- итоговое локальное состояние по `aidartest-001` дошло до `last_block_number=13`.
- В `Dev_Docs/Blockchain/sync-between-servers.md` добавлен практический результат ручной проверки на тестовом сервере.
## 2026-06-26 17:03:22 +0400
- Базовый коммит-ориентир: `71fdee0`.
- Обычный `AddBlock` переведён на crash-safe схему через временный кандидат `<blockchainName>.tmp_bch`, sidecar `<blockchainName>.write_check` и marker `<blockchainName>.write_pending`.

View File

@ -241,3 +241,16 @@ Full resync запускается только тогда, когда:
Следующие отдельные шаги после текущего этапа:
- отдельно проверить full-resync и startup-recovery на реальном тестовом прогоне после ручного удаления БД/файлов.
### 8.1 Практическая проверка на тестовом сервере
Проверка на `t.shineup.me` показала, что текущая схема действительно поднимает цепочку при старте:
- после рестарта сервер сначала проходит `BlockchainTmpRecovery`;
- затем обрабатывает `BlockchainResyncRecovery`;
- после этого сам догружает цепочку `aidartest-001` с `shineup.me`;
- итоговое состояние на тестовом сервере:
- `blockchain_state.last_block_number = 13`
- `blocks` по `aidartest-001` = `14` записей
Это подтверждает, что startup sync и full-resync flow работают в живом сценарии, а не только в коде.

View File

@ -1,13 +0,0 @@
# Стартовая загрузка `sync_servers` из server PDA
- Краткое описание:
- При запуске сервер читает свой логин из `server.SHiNE.login`, загружает свою server PDA из Solana, достаёт `sync_servers`, затем читает PDA партнёров и сохраняет их `login + server_address + updated_at_ms` в локальную таблицу `sync_servers`.
- Что проверять:
- В `application.properties` задан `server.SHiNE.login=shineupme`.
- После старта сервера в SQLite появилась/обновилась таблица `sync_servers`.
- В таблице лежат логины и адреса серверов из `sync_servers` текущего server PDA.
- При изменении `sync_servers` или `server_address` в Solana и перезапуске сервера локальная таблица обновляется.
- Ожидаемый результат:
- Сервер без ручного ввода адресов подтягивает партнёров синхронизации из Solana PDA и хранит их локально для следующих этапов репликации.
- Статус:
- `pending`

View File

@ -1,15 +0,0 @@
# Фоновая one-shot синхронизация `AddBlock` на `sync_servers`
- Краткое описание:
- После успешного локального `AddBlock` сервер в фоне пытается отправить тот же блок всем партнёрам из локальной таблицы `sync_servers`.
- Если партнёр отвечает `bad_prev_hash` или `bad_block_number`, сервер один раз делает backfill: читает недостающие блоки из БД по диапазону и досылает их по одному.
- Если в процессе возникает новая ошибка, попытка для этого партнёра прерывается без повторов.
- Что проверять:
- При добавлении нового блока клиент получает быстрый `OK`, не ожидая завершения межсерверной рассылки.
- В логах видно попытки отправки на адреса из `sync_servers`.
- При отставании партнёра сервер досылает пропущенный хвост блоков по одному.
- При ошибке после backfill сервер не зацикливается и не блокирует основной `AddBlock`.
- Ожидаемый результат:
- Репликация `AddBlock` работает в фоне и не ломает основной путь записи блока.
- Статус:
- `pending`

View File

@ -1,30 +0,0 @@
# Периодическая межсерверная синхронизация блокчейнов
- Краткое описание:
- При старте сервер подтягивает `sync_servers` из server PDA и сохраняет адреса партнёров в локальную таблицу.
- После успешного локального `AddBlock` работает фоновая one-shot отправка нового блока партнёрам.
- Добавлен публичный `GetBlockchainBlock` для чтения одного блока.
- Добавлен публичный `GetSyncUserProfile` для подготовки отсутствующей локальной цепочки без прямого Solana RPC.
- Добавлен плановый sync блокчейнов при старте сервера и затем каждые `12` часов.
- Синхронизация пока умеет только докачивать отсутствующий хвост цепочки.
- Добавлена настройка `sync.importUserProfileFromPartner.enabled`, которая включает создание локального `solana_users + blockchain_state` по ответу сервера-партнёра вместо Solana PDA.
- Случай рассинхрона цепочек пока не исправляется автоматически: он только логируется как не реализованный сценарий.
- Что именно проверять:
- После старта сервера в логах появляется запуск периодического sync.
- Сервер может запросить у партнёра `ListBlockchainHeads`.
- Сервер может запросить у партнёра `GetSyncUserProfile`, если включён `sync.importUserProfileFromPartner.enabled=true`.
- Сервер может запросить у партнёра `GetBlockchainBlock` и локально применить блок через существующий `AddBlock`.
- На чистом тестовом сервере после удаления БД и файлов блокчейнов сервер сам подтягивает блоки при старте.
- При включённом режиме обхода Solana сервер восстанавливает локальные цепочки без запросов в Solana RPC.
- После первичного старта новые блоки продолжают догоняться без ручного вмешательства.
- При рассинхроне цепочек в логах появляется явное сообщение, что reconciliation пока не реализован.
- Ожидаемый результат:
- Чистый сервер после старта сам восстанавливает локальные цепочки от партнёра синхронизации.
- В режиме обхода Solana чистый сервер не упирается в `Solana RPC 429` при создании локальных chain-state для уже существующих на партнёре пользователей.
- Периодический sync не мешает обычной работе сервера и не ломает локальный `AddBlock`.
- Нереализованный случай рассинхрона не приводит к падению сервера и явно отражается в логах.
- Статус:
- `pending`

View File

@ -1,19 +0,0 @@
# DAO очистки одной blockchain-цепочки перед полным resync
- Краткое описание:
- Добавлен отдельный DAO-метод, который в одной SQL-транзакции очищает одну blockchain-цепочку перед её полной повторной загрузкой.
- Внутри транзакции сначала уменьшаются чужие `likes_count` и `replies_count`, которые были увеличены блоками удаляемой цепочки.
- Затем удаляются локальные записи цепочки и её derived-state.
- Файлы `.bch` / `.tmp_bch` этот DAO не удаляет: файловый шаг будет отдельной следующей задачей.
- DAO уже используется в periodic full-resync flow, но это ещё не было вручную проверено на прод-цикле.
- Что именно проверять:
- Метод корректно компилируется и не ломает сборку.
- Метод подключён в рабочий periodic full-resync path, но manual e2e verification ещё нужна.
- Комментарии в коде понятны и соответствуют реальному порядку SQL-шагов.
- Ожидаемый результат:
- Появилась изолированная транзакционная точка очистки одной цепочки, на которую можно безопасно опереться при следующем шаге реализации divergence-resync.
- Статус:
- `pending`

View File

@ -1,17 +0,0 @@
# Startup recovery для marker-file resync цепочек
- Краткое описание:
- При старте сервер сканирует `data/*.resync_pending` и добивает незавершённые full-resync цепочки перед тем, как перейти к обычной работе.
- Пока marker-file не убран, обычный `AddBlock` в эту цепочку возвращает `chain_resync_in_progress`.
- Что именно проверять:
- Сервер не начинает обычный `periodic sync`, пока не отработают все marker-file recovery.
- Если marker-файлы есть, startup-blocking реально останавливает нормальный старт до их обработки.
- Если восстановление одной цепочки падает, marker остаётся на диске и сервер не переходит в обычный режим.
- После успешного восстановления marker удаляется.
- Ожидаемый результат:
- После внезапной перезагрузки сервер не продолжает обычную работу с поломанной цепочкой, а сначала добивает незавершённый resync.
- Статус:
- `pending`

View File

@ -0,0 +1,29 @@
# Проверка аварийных остановок на разных этапах
## Кратко
Нужно отдельно проверить, как сервер восстанавливается после внезапной остановки:
1. во время обычного `AddBlock` / `tmp_bch`-pipeline;
2. во время `full resync` цепочки;
3. во время startup recovery, если остановка произошла на предыдущем запуске;
4. при обычном апгрейде сервиса без явного crash-сценария.
## Что проверять
1. Остановка сервиса до `commit` БД.
2. Остановка сервиса после `commit`, но до замены `main.bch`.
3. Остановка сервиса во время `BlockchainResyncCleanupDAO`.
4. Остановка сервиса во время повторной загрузки цепочки по `GetBlockchainBlock`.
5. Поведение при обычном `systemctl restart`, когда сервер сам должен добить recovery.
## Ожидаемый результат
- после старта сервер либо дочищает временные артефакты, либо завершает незаконченный `resync`;
- не остаётся битых `.tmp_bch`, `.write_check`, `.write_pending`, `.resync_pending`;
- БД и файлы цепочки остаются согласованными;
- обычная работа сервера не стартует поверх незавершённого recovery.
## Статус
`pending`

View File

@ -1,2 +1,2 @@
client.version=1.2.278
server.version=1.2.258
client.version=1.2.279
server.version=1.2.259