Синхронизация данных после возвращения сети

Пользователь оффлайн отметил 50 операций. Сеть вернулась. Как отправить всё в правильном порядке и не потерять.

Синхронизация данных после возвращения сети

Локальное хранение действий — половина задачи. Вторая — корректно отправить их когда сеть вернётся. Тут много граблей.

Синхронизация данных после возвращения сети
Жизненный цикл оффлайн-операции — от тапа до сервера.

Структура очереди

  • Каждое действие в IndexedDB как отдельная запись с полями: id, type, payload, createdAt, retries, status
  • Status: pending → sending → done или failed
  • Сортировка по createdAt — отправляем в порядке создания

Когда отправлять

  • Background Sync API — браузер сам разбудит SW когда сеть появится. Поддержка только в Chrome/Edge на 2026
  • Online event — `window.addEventListener('online', flush)` — работает везде, но ловит только переход offline→online
  • Periodic check — каждые 30 секунд пробуем отправить, если есть pending. Старая школа, надёжно
  • Лучшее — комбинация: Background Sync где есть, online event как fallback, periodic check как safety net

Retry logic

  • Exponential backoff: 1s, 2s, 4s, 8s — но не больше 5 минут
  • Maximum retries: 5-10 попыток. После — пометить как failed, показать UI
  • Сетевые ошибки — retry. 4xx ответы (401, 403, 404, 422) — не retry, сразу failed
  • 5xx ответы — retry с увеличением задержки

Конфликты

Самое сложное. Два пользователя оффлайн-исправили одну запись. Что делать:

  • Last-write-wins — побеждает последнее изменение. Простое, но теряются данные
  • Optimistic locking — у каждой записи есть version. Сервер отвергает, если version старее текущей. UI просит решить конфликт
  • CRDT — структуры данных, которые мерджатся автоматически. Сложно, но для совместного редактирования — единственный путь

UI

  • Бейдж счётчика непросинхронизированных в углу экрана
  • Тап → список действий с возможностью retry или delete
  • При неуспехе после всех retry — нотификация с действиями