# ADR-002: Паттерн офлайн-очереди **Дата:** 2026-03-20 **Статус:** Accepted **Автор:** Architect Agent (Kin pipeline, BATON-001) **Решения:** #1001, #1003, #1006 --- ## Контекст Baton — приложение экстренного сигнала. Критичное требование: сигнал не должен быть потерян, если пользователь нажал кнопку в момент отсутствия сети (тоннель, слабый сигнал, офлайн). Данный ADR фиксирует исходное архитектурное решение по паттерну офлайн-очереди. Актуальная реализация с деталями вариантов — в ADR-007. --- ## Решение **IndexedDB outbox + BackgroundSync + online event fallback** 1. Кнопка нажата → немедленная попытка `fetch('/api/signal')` 2. Ошибка или offline → запись в IndexedDB outbox 3. Trigger 1: `window.addEventListener('online', flushOutbox)` — main thread, все браузеры 4. Trigger 2: SW регистрирует `registration.sync.register('flush-outbox')` — Chromium только --- ## Обоснование - **#1006:** IndexedDB — единственный вариант, доступный и в main thread, и в Service Worker. Общее хранилище исключает дублирование кода между `app.js` и `sw.js`. - **#1003:** localStorage в iOS Safari приватном режиме бросает `SecurityError` → не подходит для надёжного офлайн-хранилища в приложении экстренного сигнала. - **BackgroundSync (#1001):** браузер управляет повтором, flush возможен даже при закрытой вкладке (Chrome). Dual trigger (BackgroundSync + online event) страхует пользователей Safari/Firefox. --- ## Open Questions **Вопрос о покрытии BackgroundSync:** Решение #1001 фиксирует охват BackgroundSync как ~85%. Актуальные данные caniuse (март 2026) показывают 78.75% — Safari и Firefox не поддерживают API. Это влияет на описание архитектурных гарантий: ручной online-fallback является **обязательным**, а не опциональным элементом. ACTION: Обновить решение #1001 — изменить охват BackgroundSync с 85% до 78.75%, пометить ручной fallback как обязательный элемент архитектуры (конвенция #1049).