Офлайн-доставка событий

В gravity_sdk 0.24.0 очередь включена по умолчанию. SDK сохраняет запрос события на устройстве перед отправкой и повторяет доставку при временных ошибках. Это помогает сохранить действия при нестабильной сети и перезапуске приложения.

Что сохраняется

Запрос Постоянная очередь
triggerEvent() / triggerEventNoShow() Да: запрос /event, включая список событий
Результат встроенной in-app формы Да: отправка результата через /event
trackView() / trackViewNoShow() Нет
getContentBy*, inline, tooltip Нет
Content/product engagement и tracking URL Нет

Запись соответствует запросу, а не одному событию: список events может включать несколько действий. Повторные попытки сетевых запросов и постоянная очередь — разные механизмы.

Настройки

GravitySDK.instance.setOptions(
  offlineQueue: const OfflineQueueSettings(
    enabled: true,
    maxEntries: 500,
    maxAge: Duration(days: 7),
  ),
);
Настройка По умолчанию Поведение
enabled true Разрешает добавление и отправку из очереди
maxEntries 500 При переполнении старейшие записи удаляются
maxAge 7 дней Просроченные записи удаляются вместо отправки

maxEntries должен быть положительным. Для отключения задайте OfflineQueueSettings(enabled: false). Уже сохранённые записи остаются на диске, но не отправляются, пока очередь снова не включена. Отключение не равно очистке.

Если хотите изменить настройки до первой отправки старых записей, вызовите setOptions() перед initialize(). Не переключайте ключ/секцию для накопленных запросов одной и той же локальной установки: доставка и очистка очереди должны соответствовать выбранному окружению.

Когда повторяется отправка

SDK пытается доставить очередь:

  • при запуске после initialize();
  • при возвращении приложения на передний план;
  • после успешного онлайн-запроса, который показывает, что сеть снова доступна;
  • по таймеру повторных попыток;
  • после включения очереди или ручного flushQueue().

Очередь не устанавливает отдельный монитор подключения ОС. Если приложение уже следит за сетью, из его callback можно вызвать:

await GravitySDK.instance.flushQueue();
final int pending = await GravitySDK.instance.pendingDeliveries;

flushQueue() дожидается опустошения очереди либо остановки из-за ошибки; его завершение не гарантирует, что всё доставлено. При отключённой очереди это no-op. pendingDeliveries показывает число сохранённых ожидающих запросов, включая находящиеся в отправке, а не число отдельных событий.

Это не системная фоновая служба. Когда приложение не работает, SDK сам отправку не выполняет. Восстановление сети без пробуждения приложения не гарантирует немедленную доставку.

Время и пользователь

Если eventTime задан, SDK сохраняет это время. Иначе фиксирует время вызова события. Повторная доставка не заменяет его временем отправки.

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

Результаты отложенной доставки не запускают запоздалый показ in-app. Очередь доставляет события; получение актуального контента для нового экрана — отдельный запрос.

Очистка

await GravitySDK.instance.clearQueue();

Метод удаляет ожидающие запросы без восстановления; работает и при отключённой очереди. Вызывайте его только когда приложение действительно должно отказаться от доставки этих действий, например на общем устройстве по правилам удаления данных.

resetUser() сам очередь не очищает. Последовательность выхода с очисткой:

await GravitySDK.instance.clearQueue();
await GravitySDK.instance.resetUser();

На время операции остановите создание новых событий. Уже отправленный в сеть запрос не отменяется; ожидающий сессию запрос из очищаемой очереди не должен уйти позже. Если хранилище отказало в очистке, clearQueue() выбрасывает исключение — не считайте данные удалёнными.

Ограничения и повторная доставка

Временные сетевые ошибки и ответы 408/429/5xx допускают повторные попытки. Другие 4xx, ошибки парсинга и отмена не исправляются обычным повтором. Серверные ошибки имеют ограниченное число попыток; постоянная недоставка не хранится бесконечно.

Если сервер обработал событие, но ответ потерялся, возможен дубль. SDK не обещает exactly-once. Для покупки используйте постоянный уникальный uniqueTransactionId заказа. Не генерируйте новый ID при повторной отправке.

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

Проверка на устройстве

  1. Отправьте покупку при недоступной сети с уникальным ID тестового заказа.
  2. Проверьте, что число ожидающих запросов увеличилось.
  3. Перезапустите приложение без сети: запись должна остаться, если не истёк срок хранения.
  4. Восстановите соединение и вызовите flushQueue().
  5. Проверьте доставку с исходным временем и пользователем.
  6. Повторите со сменой аккаунта; отдельно проверьте явную очистку.
  7. Убедитесь, что старые in-app сообщения после доставки не появляются.

Для формы аналогично проверяется доставка ответа, но её tracking URL сами в постоянной очереди не сохраняются.