Offline-first запись
Полевой пользователь (бурильщик, мастер смены) работает там, где связи нет или она рвётся. Сменный рапорт нельзя терять и нельзя дублировать. Этот рецепт показывае т, как включить offline-устойчивую запись по ADR-0049: мутация офлайн паузится (а не падает), очередь персистится на диск и доигрывается строго по порядку при возврате связи или после рестарта приложения.
Все write-хуки сменного рапорта (useCreateShiftReport, useAdd*, useSubmitShiftReport, useRejectShiftReport из @mineflow/client-react) уже offline-ready из коробки. Включить нужно только персист + replay-defaults (один раз в провайдере) и, по желанию, UI-индикатор очереди.
Approve и reject-after-approve — это саги: они поллят статус и требуют связи, поэтому остаются online-only. Их в offline-домен не включают. Про саги — отдельный рецепт «Async-саги».
Как это работает: три кита
Offline-устойчивость держится на трёх вещах. Менять их по отдельности нельзя — выпадет любой из них, и гарантия ломается.
- Стабильный
Idempotency-Keyвvariables. Ключ генерируется один раз при энкью мутации и кладётся в еёvariables. Он переживает рестарт (персистится вместе с мутацией) и переиспользуется на каждой попытке replay. Бэкенд дедуплицирует повтор по этому ключу — поэтому проиграть одну и ту же запись дважды безопасно. - Общий
scope. Все операции домена сериализуются TanStack Query строго FIFO (черезMutationCache), потому что у них одинscope.id. Без этогоcreate → addAssetUsage → submitпроигрались бы конкурентно, иsubmitушёл бы раньше, чем рапорт создан. networkMode: 'online'(дефолт TanStack Query). ОфлайнmutationFnне вызывается — мутация переходит вpaused, а не вerror. Авто-resume происходит поonlineManager, когда связь вернулась.
Эти три вещи работают только вместе. Если задать мутации networkMode: 'always', она не будет паузиться — упадёт офлайн. Если у операций разный scope — replay пойдёт не по порядку. Если Idempotency-Key нестабилен (генерится в mutationFn) — повтор после рестарта создаст дубль.
Механику целиком инкапсулирует объект shiftReportDomain — инстанциация фабрики createOfflineDomain. Вызовы эндпоинтов в нём — единственный источник истины: их используют и live-хуки (useCreateShiftReport и т.д.), и replay восстановленных из персиста мутаций.