Skip to content

Latest commit

 

History

History
121 lines (79 loc) · 3.73 KB

File metadata and controls

121 lines (79 loc) · 3.73 KB

Синхронизация данных

Изменено: 02.06.2026

Синхронизация построена вокруг очереди операций (SyncQueue). Модули приложения сначала меняют локальные данные, а затем sync постепенно отправляет накопленные изменения на сервер.

Основные части

В реализации участвуют:

  • SyncManager
  • SyncRepository
  • SyncQueue
  • SyncScheduler
  • SyncRemoteDataSource
  • SyncLocalDataSource

Главная точка входа - SyncManager.

requestSync()
forceSync(retry)
status: StateFlow<SyncStatus>

Статусы

Во время работы используются состояния:

  • Ok
  • InProcess
  • Failed
  • WouldRetry(inSeconds)

Последнее состояние показывает, что запрос завершился ошибкой и система ждёт следующей попытки.

Когда запускается синхронизация

Запуск идёт через SyncScheduler.

Он наблюдает за очередью несинхронизированных операций:

queueRepo.getUnsyncedFlow()

После debounce создаётся запрос на синхронизацию.

Защита от параллельных запусков

В SyncManagerImpl используются:

  • Mutex
  • withWebLock(...)
  • SupervisorJob

Это нужно, чтобы несколько вкладок или несколько событий не запускали синхронизацию одновременно.

Повторные попытки

При ошибках используется экспоненциальная задержка:

10s
20s
40s
80s
...
до 5 минут

Во время ожидания статус переключается в WouldRetry(...).

Как выглядит запрос

Unsynced queue rows
  -> mapSyncQueueRow(...)
  -> SyncRequest
  -> sendSyncRequest(...)
  -> SyncResponse

На сервер отправляются накопленные операции из очереди.

Как обрабатывается ответ

Сервер возвращает несколько частей ответа.

acceptedIds используются для удаления успешно обработанных операций из локальной очереди.

deleteOperations применяются к локальному состоянию. В коде используются операции удаления счетов, категорий, переводов и транзакций.

updateState содержит актуальное состояние сущностей. Оно применяется через репозитории:

  • accountsRepo.upsertAccount(...)
  • categoriesRepo.upsertCategory(...)
  • transactionsRepo.badInsertTransfer(...)
  • transactionsRepo.badInsertTransaction(...)

Авторизация

Без токенов синхронизация не запускается.

Перед отправкой запроса проверяется:

TokenStorage.isTokensEmpty()

Если пользователь не авторизован, запрос не выполняется.

При запуске приложения

Во время старта вызывается:

syncManager.forceSync(false)

За счёт этого локальное состояние пытается синхронизироваться с сервером сразу после инициализации приложения.