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 и наблюдаемую очередь.