Offline Queue: principy, strategie a mechanismy fungování

Autor: IT Sectr Publikováno: 2026-06-13 Doba čtení: 10 min

Offline Queue — je mechanismus, který ukládá uživatelské operace lokálně, když je zařízení offline, a odesílá je na server po obnovení připojení. Bez offline fronty uživatel ztrácí všechny akce provedené bez internetu, což je v mobilních aplikacích nepřípustné. Podle Google Developers (2025) zvyšuje zavedení offline-first architektury udržení uživatelů o 30% v regionech s nestabilním internetem.

Hlavní body

  • Offline Queue — FIFO fronta operací, které uživatel provádí bez internetu, pro následnou synchronizaci.
  • Persistent storage — fronta je uložena v lokální DB (SQLite, Room) pro zachování při restartu aplikace.
  • Exponential backoff — strategie opakovaných pokusů s rostoucím intervalem při selhání odeslání.
  • Conflict resolution — mechanismus řešení konfliktů, když offline změny kolidují s daty na serveru.
  • Idempotency keys — unikátní klíče operací pro zabránění duplicitě na serveru při opětovném odeslání.

Co je offline fronta?

Offline Queue — je uspořádaná kolekce operací (vytvoření, aktualizace, smazání), kterou aplikace ukládá lokálně, když zařízení nemá přístup k síti. Jakmile je připojení obnoveno, fronta odesílá operace na server ve stejném pořadí, v jakém je uživatel provedl.

Představte si scénář: uživatel chatovací aplikace píše zprávy v metru bez internetu. Každé stisknutí „Odeslat“ se přidá do Offline Queue. Když vlak vyjede z tunelu a objeví se síť, všechny zprávy se automaticky odešlou. Uživatelský zážitek — plynulý: nevšimne si, že byl offline, kromě mírného zpoždění při odesílání.

Podle Uber Engineering (2024) zpracovává jejich offline fronta více než 2 miliony operací denně v regionech s nízkou kvalitou připojení. Fronta používá lokální úložiště Room s FIFO řazením a mechanismem zaručeného doručení exactly-once.

kotlin
data class QueuedOperation(
    val id: String,
    val type: OperationType,
    val endpoint: String,
    val payload: String,
    val timestamp: Long,
    val retryCount: Int = 0,
    val idempotencyKey: String
)

Každá operace obsahuje všechna data potřebná k opětovnému odeslání: endpoint, tělo požadavku, časové razítko a idempotencyKey. Room-DB zaručuje zachování fronty při restartu aplikace a selhání OS.

Proč je fronta operací potřebná v mobilní aplikaci

Záruka doručení — hlavní úkol fronty. Uživatel musí mít jistotu, že jeho akce (odeslání zprávy, like, objednávka) bude provedena, i když síť není v okamžiku provedení dostupná. Offline Queue s mechanismem retry zajišťuje doručení eventually.

Zlepšení UX při špatném připojení — podle GSMA Mobile Economy Report (2025) má přibližně 40% mobilních uživatelů na světě nestabilní internetové připojení. Offline Queue činí aplikaci použitelnou v metru, výtazích, odlehlých oblastech — všude, kde je připojení přerušované.

Snižení ztráty dat — bez fronty se všechny akce provedené offline ztratí. Uživatel může vyplnit dlouhý formulář, stisknout „Odeslat“ a vidět chybu sítě — veškerý vstup je ztracen. Offline Queue ukládá data a odesílá je při první příležitosti. Auto-save v Google Docs — klasický příklad offline fronty pro dokumenty.

Asynchronní synchronizace — fronta umožňuje aplikaci neblokovat UI během odesílání. Uživatel pokračuje v práci, zatímco správce synchronizace zpracovává frontu na pozadí. To je v souladu s principy Reactive Architecture a zlepšuje odezvu rozhraní.

Architektura offline fronty: ukládání a zpracování

Tři vrstvy fronty: úložiště (persistence), plánovač (scheduler) a procesor (executor). Úložiště — Room s tabulkou QueuedOperation. Plánovač — WorkManager (Android) nebo BGTaskScheduler (iOS), který spouští synchronizaci při výskytu sítě. Procesor — sekvenční iterátor FIFO odesílající operace jednu po druhé.

Pořadí zpracování — kritické pro konzistenci dat. Pokud uživatel vytvořil záznam a poté jej upravil, obě operace musí být odeslány ve stejném pořadí. Jinak server nejprve obdrží aktualizaci neexistujícího záznamu — chyba. Sequential FIFO — přísné pořadí s kontrolou závislostí mezi operacemi.

Strategie slučování — pokud je ve frontě CREATE a hned po něm DELETE stejného objektu, lze obě operace odstranit bez odeslání: konečný stav — objekt nebyl vytvořen. Podobně, CREATE + UPDATE téhož CREATE lze sloučit do jednoho CREATE s nejnovějšími daty. Optimalizace fronty snižuje počet HTTP požadavků a urychluje synchronizaci.

Podle Android Developers (2025) je WorkManager preferovaný způsob zpracování Offline Queue na Androidu: zaručuje provedení i po restartu zařízení, podporuje constraints na přítomnost sítě a umožňuje nastavit politiku opakovaných pokusů přes NetworkType.CONNECTED.

kotlin
class SyncWorker(
    private val context: Context,
    private val params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result = runCatching {
        queueRepository.processNextBatch(batchSize = 10)
        Result.success()
    }.getOrDefault(Result.retry())
}

CoroutineWorker zpracovává dávky operací a vrací Result.retry() při selhání — WorkManager automaticky opakuje spuštění s exponenciální prodlevou. Toto je nejjednodušší způsob, jak získat spolehlivou Offline Queue na Androidu.

Strategie opakovaných pokusů: exponential backoff a politika retry

Exponential Backoff — standardní strategie opakování s rostoucím intervalem: 2 s, 4 s, 8 s, 16 s a tak dále až do maximálního limitu. To zabraňuje opakovanému přetížení serveru, pokud je dočasně nedostupný. Java knihovna Resilience4j (2024) poskytuje hotovou implementaci Retry s konfigurovatelným backoff.

Maximální počet pokusů — kritický parametr. Pokud se po 5–10 pokusech operace nezdařila, další opakování jsou zbytečná. Doporučuje se dead letter queue: po vyčerpání pokusů se operace přesune do samostatné tabulky pro ruční analýzu. Podle Microsoft Patterns & Practices (2024) dead letter queue zjednodušuje ladění problémů synchronizace a zabraňuje blokování fronty chybnými operacemi.

Jitter — náhodná variace — přidání náhodného čísla k intervalu backoff. Pokud tisíc zařízení současně získá síť po odpojení, všechna spustí synchronizaci najednou. Jitter je časově rozloží a zabrání Cache Stampede na serveru. Plný jitter: delay = random(0, backoff) — doporučeno AWS (2024) pro API klienty.

Řešení konfliktů: jak řešit kolize dat

Last Write Wins (LWW) — nejjednodušší strategie: při konfliktu vítězí operace s novějším časovým razítkem. LWW vyžaduje synchronizaci času — časové razítko musí být generováno na serveru nebo používat Logical Clock (Lamport clocks). Nevýhoda: data jednoho uživatele mohou být přepsána daty jiného bez varování.

OT (Operational Transformation) — algoritmus používaný Google Docs a Figma pro spolupráci v reálném čase včetně offline režimu. OT transformuje operace tak, aby se aplikovaly na jakýkoli stav dokumentu, zajišťující konzistenci bez zámků. CRDT (Conflict-Free Replicated Data Types) — alternativa k OT získávající popularitu v mobilních aplikacích: data jsou strukturována tak, že konflikty jsou řešitelné matematicky bez centrálního serveru.

Custom Merge — pro aplikace s jednoduchým datovým modelem (poznámky, kontakty) lze implementovat vlastní pravidla slučování. Například pro poznámku: pokud byl text změněn ve dvou verzích, spojit je jako konkatenaci s oddělovačem. Konflikt řešený uživatelem — pokud automatické sloučení není možné, zobrazit uživateli obě verze a nabídnout výběr. Dropbox (2024) používá tento přístup pro konflikty v offline souborech a vytváří kopie s prefixem „Conflicted Copy“.

Idempotency keys — ochrana před duplicitou

Idempotency Key — unikátní identifikátor operace, který server používá k detekci duplicitních požadavků. Pokud klient odešle stejný požadavek se stejným klíčem, server vrátí výsledek již provedené operace, aniž by ji provedl znovu. To je kriticky důležité pro Offline Queue, kde jsou možné opakované odeslání při síťových chybách.

Formát idempotency key — UUID nebo hash parametrů požadavku. Server musí ukládat provedené klíče spolu s výsledkem po určitou dobu (obvykle 24 hodin) pro detekci duplicit. Stripe API (2024) — vzorový příklad: klíč se přenáší v hlavičce Idempotency-Key a opakované požadavky se stejným klíčem vracejí odpověď z cache.

Generování na klientovi — klíč se vytváří na klientovi před odesláním operace a ukládá se do tabulky QueuedOperation. Při opakovaném pokusu se klíč nemění. Architektura exactly-once — kombinace idempotency key na klientovi a deduplikace na serveru — jediný způsob, jak zaručit, že operace nebude provedena dvakrát.

kotlin
fun createOperation(type: OperationType, payload: String): QueuedOperation =
    QueuedOperation(
        id = UUID.randomUUID().toString(),
        type = type,
        endpoint = type.endpoint,
        payload = payload,
        timestamp = currentTimeMillis(),
        idempotencyKey = UUID.randomUUID().toString()
    )

Každá operace obdrží dvě UUID: jedno — identifikátor záznamu ve frontě, druhé — idempotency key pro server. Serverová deduplikace podle idempotencyKey zaručuje, že i při opětovném odeslání nebude objednávka duplikována.

Často kladené otázky

Čím se Offline Queue liší od cache?

Cache ukládá kopie dat pro rychlé čtení offline. Offline Queue ukládá operace uživatele pro následný zápis na server. Cache funguje pro čtení, fronta — pro zápis. Oba komponenty mohou koexistovat v offline-first architektuře.

Jaká velikost fronty je bezpečná pro mobilní zařízení?

Doporučený limit — 100–500 operací. Více — riziko přetečení paměti a dlouhé synchronizace při obnovení sítě. Při překročení limitu by aplikace měla uživatele varovat a nabídnout prioritizaci operací. Rozumné omezení — 50 operací na aktualizaci + 10 na vytvoření.

Jak zpracovávat zastaralé operace ve frontě?

Operace starší 7 dnů s nulovým úspěchem se přesouvají do dead letter queue. Analyzujte je ručně: možná se změnilo API a endpoint již neexistuje. Automatické čištění — úloha HealthCheck jednou denně maže nebo archivuje prošlé operace.

Co dělat, pokud operace závisí na předchozí, která ještě nebyla odeslána?

Použijte graf závislostí (DAG): každá operace obsahuje seznam parentOperationId, které musí být dokončeny před jejím odesláním. Dotaz Room s ORDER BY parent vrátí operace ve správném pořadí. Kaskádové odesílání — po dokončení každé operace zkontrolujte, zda nebyly odblokovány podřízené operace.

Jak testovat Offline Queue?

Použijte Network Less Tool v Android Emulator nebo Network Link Conditioner v iOS Simulator pro simulaci ztráty sítě. Napište testy, které přidávají operace do fronty v offline režimu, obnoví připojení a zkontrolují, že všechny operace byly odeslány a zpracovány serverem.

Shrnutí

  • Offline Queue — FIFO fronta operací uložená lokálně pro odeslání po obnovení připojení.
  • Persistent storage (Room / SQLite) — nutný pro zachování fronty při restartu aplikace.
  • Exponential backoff s jitterem — standardní strategie opakování pro zabránění přetížení serveru.
  • Conflict resolution — LWW, OT, CRDT nebo vlastní pravidla pro řešení kolizí offline dat.
  • Idempotency key — UUID každé operace pro zajištění exactly-once doručení na serveru.
  • Dead letter queue — izolace problémových operací po vyčerpání pokusů pro ruční analýzu.
  • Nejlepší praxe pro Android — WorkManager + Room + ExponentialBackoff — osvědčená kombinace od Googlu.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také