Background Sync не является гарантированной фоновой очередью: браузер решает, когда разбудить service worker, а некоторые платформы ограничивают или не поддерживают API. Накопленные данные должны надежно храниться локально и отправляться также при следующем открытии приложения, а сервер обязан безопасно принимать повторы.

Проверьте поддержку API, состояние регистрации service worker, наличие записей в IndexedDB и факт регистрации sync tag. Реализуйте явный fallback на online/startup и не удаляйте запись из очереди до подтвержденного ответа сервера.

Что проверить в первую очередь

Начните с воспроизводимого сценария: зафиксируйте время сбоя, идентификатор объекта, версию приложения или конфигурации и последнее известное рабочее состояние. Не меняйте несколько параметров одновременно. Один контролируемый шаг должен подтверждать или исключать одну гипотезу, иначе временное исчезновение симптома легко принять за исправление. Перед работой с данными и настройками подготовьте резервную копию и понятный способ отката.

  • Убедитесь, что приложение работает по HTTPS и активен ожидаемый service worker.
  • Проверьте наличие serviceWorker.ready и sync.register без rejected promise.
  • Откройте IndexedDB и посмотрите реальные накопленные записи.
  • Уточните браузер, ОС, режим энергосбережения и поддержку Background Sync.

Почему возникает проблема

Внешний симптом часто появляется не в том компоненте, где возникла первичная ошибка. Интерфейс может показывать неверное состояние из-за backend, очереди, кеша, прав доступа или внешнего API. Полезно проследить данные от источника до результата и найти первую точку расхождения. Это надежнее, чем исправлять последнее сообщение об ошибке или бесконечно перезапускать сервис.

  • Service worker обновился, но новая версия ожидает activation.
  • Sync tag зарегистрирован до сохранения операции в IndexedDB.
  • Запись удаляется из очереди сразу после fetch, не дожидаясь успешного бизнес-ответа.
  • Браузер не поддерживает API или долго не дает фоновое время.
  • Один ошибочный элемент прерывает обработку всей пачки.

Пошаговая диагностика

Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли, персональные данные и содержимое документов. Для каждого шага сохраняйте измеримый результат: код ответа, версию записи, идентификатор события, состояние процесса, контрольную сумму или время выполнения. Сравнение одной и той же операции до и после изменения помогает отделить причину от совпадения.

  • Логируйте жизненный цикл install/activate и версию worker.
  • Проверьте очередь до sync, во время события и после ответа сервера.
  • Имитируйте offline в DevTools, создайте одну запись и верните сеть.
  • Проверьте waitUntil: promise должен охватывать всю отправку и изменение очереди.
  • Сравните поведение Chrome Android, desktop и неподдерживаемых браузеров.

Как должна работать надежная offline-очередь

Источником истины является локальная запись операции с уникальным ID, а Background Sync — лишь один из способов инициировать доставку. Потеря фонового события не должна означать потерю пользовательских данных.

  • Операция сначала атомарно сохраняется в IndexedDB со статусом pending.
  • После сохранения регистрируется sync tag и обновляется интерфейс.
  • Worker берет ограниченную пачку и отправляет idempotency key.
  • Запись удаляется или становится sent только после подтверждения сервера.
  • При ошибке сохраняются attempts и next_retry_at, а приложение пробует снова при startup/online.

Как исправить проблему

Разбейте исправление на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовое обновление данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем. Не отключайте авторизацию, валидацию, шифрование или проверку сертификатов ради быстрого исчезновения ошибки.

  • Перенесите сохранение в IndexedDB до регистрации sync.
  • Оберните полную цепочку отправки в event.waitUntil.
  • Добавьте fallback-вызов drainQueue при запуске и событии online.
  • Разделите временные и постоянные ошибки, чтобы плохая запись не блокировала очередь.
  • На сервере внедрите уникальность operation_id и возврат прежнего результата при повторе.

Безопасный порядок внедрения

  • Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив реальный способ восстановления.
  • Повторите проблему на тестовом объекте без реальных списаний, рассылок и необратимых изменений клиентских данных.
  • Зафиксируйте изменение в системе контроля версий или журнале работ вместе с причиной и планом отката.
  • Проведите тест на нормальном сценарии, ошибочном вводе, повторном запросе, параллельной операции и временной недоступности зависимости.
  • После выпуска наблюдайте логи, метрики и полный пользовательский путь, а не только один успешный запрос.

Как проверить результат

Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, одновременные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист. Итог должен подтверждаться не только интерфейсом, но и состоянием базы, очереди, внешнего сервиса и журналом действий.

  • Запись, созданная offline, сохраняется после закрытия вкладки и перезапуска браузера.
  • После восстановления сети сервер получает ее ровно один раз по бизнес-смыслу.
  • Неподдерживаемый браузер отправляет очередь при следующем открытии.
  • Ошибка одного элемента не мешает доставить остальные допустимые записи.

Типичные ошибки при исправлении

  • Хранить очередь только в памяти service worker.
  • Считать событие online доказательством доступа к API.
  • Удалять запись после HTTP-запроса без проверки статуса и ответа.
  • Показывать пользователю успех до локального сохранения операции.

Как предотвратить повторение

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

  • Показывайте статус pending/sent/error и возможность ручного повтора.
  • Тестируйте закрытие вкладки, обновление worker и долгий offline.
  • Ограничивайте размер очереди и срок хранения вложений.
  • Собирайте метрики возраста pending-записей и повторных доставок.

Что подготовить для технического разбора

  • Описание ожидаемого и фактического поведения с точной последовательностью действий.
  • Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
  • Фрагменты журналов до и после ошибки без секретов и персональных данных.
  • Перечень последних изменений и уже выполненных проверок.
  • Безопасный доступ к тестовой среде либо способ воспроизвести сбой без влияния на клиентов.

Частые вопросы

Работает ли Background Sync на iPhone?

Поддержка и ограничения меняются, поэтому проектируйте обязательный fallback на запуск приложения и событие сети.

Можно ли отправлять большие файлы?

Лучше хранить метаданные и использовать отдельную возобновляемую загрузку. Большие blobs быстро заполняют хранилище и ненадежны в коротком фоне.

Когда нужна помощь специалиста

Если PWA теряет накопленные действия или не отправляет их после появления сети, я могу проверить service worker, IndexedDB и серверную идемпотентность, добавить fallback и наблюдаемую очередь.