Обновления service worker и согласованность клиентов
Практическая модель обнаружения обновлений service worker, состояний waiting и active, безопасной перезагрузки управляемых клиентов и доказательств отката.
BotBrowser Team
Нужна структурированная документация по теме Развертывание?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
BotBrowser умеет создавать управляемые контексты браузера и показывать состояние регистрации и клиента, которое наблюдает тест. Он не меняет алгоритм обновления сервис-воркера, не превращает waiting worker в active и не решает за приложение, когда страницу безопасно перезагрузить. Контракт координации принадлежит приложению; BotBrowser предоставляет воспроизводимые контексты и точки наблюдения.
TL;DR
Обновление: это последовательность, а не одна загрузка. Обнаруживайте кандидат через ServiceWorkerRegistration.update(), наблюдайте состояния installing, waiting и active, определяйте управляемые клиенты и координируйте перезагрузку только после готовности новой версии и проверки её совместимости. Записывайте идентификаторы старого и нового скрипта, состояния клиентов, выбор пользователя и результат после перезагрузки. Если новая версия работает неверно, остановите её продвижение, восстановите последний заведомо исправный скрипт и проверьте прежнюю версию свежими доказательствами. Этот процесс не обещает, что каждый браузер получит обновление одновременно.
Contents
- Модель состояний обновления
- Согласованность управляемых клиентов
- Безопасная координация перезагрузки
- Полезные доказательства отката
- Проверка релиза
- Итоги и практический вывод
Модель состояний обновления
Пока браузер проверяет кандидат-скрипт, он сохраняет существующий active сервис-воркер. Поэтому регистрация может одновременно показывать три разных ссылки: installing во время установки кандидата, waiting после установки, но до передачи управления, и active для версии, которая сейчас обслуживает управляемые клиенты. Это наблюдаемые состояния, а не синонимы фразы «новый файл уже есть на сервере».
registration.update() просит браузер проверить URL скрипта регистрации на наличие новой версии. В справочнике MDN описан возвращаемый promise: после проверки он разрешается регистрацией, а при невозможности завершить обновление отклоняется. Разрешённый promise не доказывает, что новая версия найдена или активирована. После него прочитайте registration.installing, registration.waiting и registration.active, а для асинхронного появления кандидата подпишитесь на updatefound.
Событие statechange у устанавливаемого worker служит полезной границей для сообщения пользователю. installing означает, что кандидат ещё не готов к координированной перезагрузке. Если уже есть active worker или управляемые клиенты, installed может оставаться в состоянии waiting; при первой установке без active worker он переходит в activating и activated. Само состояние installed не означает active. activating означает переход, а не стабильный идентификатор релиза. activated доказывает, что у регистрации появился новый active worker, но странице всё ещё может понадобиться перезагрузка, чтобы оказаться под его управлением.
Небольшая таблица задаёт единственный смысл каждому переходу:
| Наблюдаемое состояние | Безопасная интерпретация | Следующее действие |
|---|---|---|
installing | Кандидат подготавливается | Оставить страницу и ждать statechange |
waiting | Кандидат готов, но существующие клиенты могут работать со старой active-версией | Показать выбор перезагрузки с пояснением совместимости |
active без изменения controller | Регистрация активна, но эта страница может оставаться под старой версией | Ждать controllerchange или осознанной навигации |
controllerchange | Версия, управляющая страницей, изменилась | Синхронизировать состояние и при необходимости перезагрузить один раз |
Не выводите состояние из временной отметки, ответа 200 или нового URL скрипта. Браузер может выполнить проверку позже, а один клиент может оставаться под старым controller, пока другой уже перешёл вперёд.
Согласованность управляемых клиентов
navigator.serviceWorker.controller сообщает, какой active worker управляет страницей, либо равен null, если управления нет. Записывайте URL скрипта controller или идентификатор релиза, который выдаёт приложение, вместе с состоянием регистрации. Так можно отличить «кандидат установлен» от «эта страница работает под кандидатом».
Приложению с несколькими вкладками нужно единое решение о моменте перехода. Одна вкладка может заметить waiting и передать другим управляемым клиентам нейтральный сигнал «обновление готово». Каждая вкладка должна показать один и тот же идентификатор релиза и позволять отложить перезагрузку. Вкладку с незаписанной формой нельзя перезагружать только потому, что другая вкладка уже готова.
Сообщение об обновлении должно содержать факты, а не команды, скрывающие переход: кандидат-релиз, текущий релиз controller, состояние готовности и идентификатор запроса. Получив сообщение, вкладка перечитывает свою регистрацию и controller. Это не даёт действовать по устаревшему сообщению после появления второго обновления.
Решающее правило: совместимость. Если кандидат меняет форматы ответов, предположения о навигации или протокол страницы, он не должен брать открытую страницу под управление без пути миграции. Для несовместимых версий укажите режим «перезагрузить вместе». Обратно совместимый кандидат может показать менее навязчивое уведомление, но всё равно должен явно проверить controller.
BotBrowser может открыть отдельные управляемые контексты и снять состояние каждой страницы. Он не может заставить два контекста использовать один controller и не определяет совместимость протокола продукта. Тест должен явно указать, какие клиенты переходят вместе, а какие могут остаться на прежней версии.
Безопасная координация перезагрузки
Сначала сообщите в интерфейсе, что обновление готово, не выполняя навигацию принудительно. Покажите релиз кандидата и короткую причину. Оставляйте выбор до безопасного момента: нельзя потерять несохранённую форму, загрузку, платёж или другую операцию. Для выбора «позже» оставьте путь через следующую навигацию.
Затем непосредственно перед перезагрузкой подтвердите состояние. Прочитайте registration.waiting, active worker и navigator.serviceWorker.controller, сравните их идентификаторы с сообщением, открывшим уведомление. При расхождении закройте уведомление и проверьте снова, а не перезагружайте страницу по устаревшим данным.
Наконец, скоординируйте переход. Страница может слушать controllerchange, прекратить принимать новую работу, сохранить только разрешённое продуктом состояние и перезагрузиться один раз. Защитите перезагрузку флагом на странице, чтобы поток событий не создал цикл. Страница, получившая controllerchange после начала навигации, завершает навигацию и записывает полученный controller.
Минимальная последовательность наблюдает состояние и не принуждает активацию:
let reloadIssued = false;
let reloadApproved = false;
function approveReload() {
reloadApproved = true;
}
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (reloadIssued || !reloadApproved) return;
if (document.querySelector('[data-unsaved-work="true"]')) return;
reloadIssued = true;
window.location.reload();
});
async function checkForUpdate(registration) {
await registration.update();
return {
installing: registration.installing?.state ?? null,
waiting: Boolean(registration.waiting),
active: registration.active?.scriptURL ?? null,
controller: navigator.serviceWorker.controller?.scriptURL ?? null,
};
}
Политика активации должна соответствовать протоколу страницы и текущей работе пользователя. Для критической формы дайте человеку закончить и проверьте controller после следующей навигации; для интерфейса только для чтения можно предложить немедленный выбор, если совместимость доказана.
Полезные доказательства отката
Откат: решение о релизе, основанное на наблюдениях. Сохраните идентификатор последнего заведомо исправного скрипта, идентификатор кандидата, версию браузера, идентификатор контекста и путь, на котором произошёл сбой. Добавьте время обнаружения обновления, активации, смены controller и завершения перезагрузки. Нужны переходы состояния, а не данные аккаунта или тела запросов.
| Точка | Сохраняемое доказательство | Решение |
|---|---|---|
| До продвижения | Идентификатор исправной версии и успешный результат пути | Базовую версию можно восстановить |
| Обнаружение кандидата | Результат update(), состояния регистрации и идентификатор кандидата | Кандидат действительно наблюдался |
| После перезагрузки | Идентификатор controller, релиз страницы и результат пути | Клиент согласованно перешёл или нет |
| После отката | Восстановленный идентификатор и новый результат пути | Откат действует, а не только настроен |
При сбое пути остановите продвижение и сравните идентификатор controller с ожидаемым релизом. Восстановите заведомо исправный скрипт обычным путём доставки, откройте новый контекст и повторите тот же путь. Клиент, уже управляемый кандидатом, может потребовать координированной навигации, чтобы показать восстановленную версию; запишите это и не объявляйте откат завершённым заранее.
Доступность старого файла сама по себе не доказывает откат. Доказательство: управляемый клиент, сообщающий восстановленную active-версию и проходящий путь, на котором произошёл сбой. Кандидат и запись сбоя можно сохранить для диагностики, но пользовательский путь должен обслуживать только принятую версию.
Проверка релиза
В воспроизводимом контексте проверьте всю последовательность:
- Загрузите базовую версию и запишите регистрацию, active-скрипт, controller и результат представительного пути.
- Разверните скрипт-кандидат и вызовите
registration.update()из уже управляемой страницы. - Записывайте
installing,waiting,active,updatefoundиstatechange, пока кандидат не перейдёт в стабильное состояние. - Откройте второй управляемый клиент и убедитесь, что он остаётся на старом controller или переходит по объявленному правилу совместимости.
- Выберите перезагрузку в одном клиенте, поймайте
controllerchangeи убедитесь, что страница перезагрузилась не более одного раза. - Повторите путь и сравните результат с базовым. Несовпадение приостанавливает продвижение.
- Запустите путь отката с той же матрицей контекстов и сохраните доказательство восстановленной версии.
BotBrowser делает эти проверки воспроизводимыми в разных управляемых контекстах и версиях браузера. Он не сертифицирует контракт совместимости приложения, не выбирает момент перезагрузки пользователя и не гарантирует единое расписание обновлений. Такие утверждения требуют продуктовых доказательств от страниц и процесса релиза.
Для общей базы проверки версий смотрите Проверку релиза браузера, а для восстановления после сетевого сбоя смотрите Восстановление сессии после сетевого прерывания.
Не записывайте только «обновление успешно». Для каждого контекста укажите версию браузера, URL скрипта, состояния installing, waiting, active, а также controller до и после уведомления. Запишите, выбрал ли пользователь «сейчас» или «позже», потому что отложенный выбор является допустимым результатом. Одна отметка успеха не различает установленного кандидата, active worker и страницу под его управлением.
Сравнивайте конкретные идентификаторы, а не только отображаемые имена. URL скрипта с неизменяемым идентификатором релиза даёт странице и тесту проверяемое значение. Если идентификатор страницы отличается от controller, оставьте текущую страницу и перечитайте состояние вместо принудительной навигации. Записывайте каждую вкладку отдельно, поскольку состояния и controller могут различаться.
Ограничьте число повторных проверок. Вызывайте update() снова только после завершения предыдущего promise и указывайте число проверок в записи. Повторные вызовы не ускоряют активацию, а бесконечный цикл может скрыть проблему сервера или совместимости. После достижения лимита сохраните наблюдаемое состояние и примите решение о релизе.
Текст интерфейса должен соответствовать состоянию. Говорите о готовой новой версии только после наблюдения waiting или нового идентификатора active; пока update() выполняется, сообщайте о проверке. При отклонении promise объясните, что проверка не завершилась, и оставьте страницу рабочей. Отключайте «перезагрузить сейчас» во время загрузки или оплаты, а перед навигацией снова проверяйте идентификаторы.
Запись приёмки должна быть понятна человеку, который не выполнял тест. Укажите путь страницы, каждое изменение controller и отдельный результат отката, сохранив исправный идентификатор и новый успешный путь. Не включайте необработанный вывод консоли и чувствительные данные, чтобы результаты можно было сравнивать между контекстами.
Службе поддержки следует также записывать, отправила ли страница событие controllerchange. Фоновая проверка должна обновлять только индикатор и снимок регистрации, а не удалять работу пользователя. Проверки браузера во время навигации должны входить в ту же модель состояний.
Используйте единый словарь: «кандидат» для installing или waiting, «active» для active-ссылки регистрации и «controller» для версии, управляющей страницей. Если кандидат отклонён, запишите состояние сбоя и назначьте следующему кандидату новый идентификатор, чтобы доказательства не смешивались.
При приёмке ответьте, завершился ли update() и наблюдался ли идентификатор, какие клиенты перешли по правилу, проверены ли идентификаторы без защищённой несохранённой работы, произошла ли не более одной перезагрузки и доказывают ли исправный идентификатор с новым успешным путём эффективный откат. Результат относится только к объявленной матрице и повторяется при изменении скрипта или протокола.
Итоги и практический вывод
Рассматривайте обновление сервис-воркера как координацию регистрации, кандидата, active-версии и управляемых клиентов. Вызывайте update() для обнаружения изменений, читайте реальные состояния, явно задавайте совместимость и перезагружайте каждый клиент только после подтверждения перехода. Связывайте доказательства отката с реальным controller и воспроизводимым пользовательским путём. BotBrowser воспроизводит эти наблюдения, но политика обновления остаётся ответственностью приложения.
Sources
Похожие статьи
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.