Offline Queue egy olyan mechanizmus, amely helyben tárolja a felhasználói műveleteket, amíg az eszköz offline állapotban van, és a kapcsolat helyreállítása után elküldi azokat a szerverre. Offline sor nélkül a felhasználó elveszíti az internet nélkül végzett összes műveletét, ami a mobilalkalmazásokban elfogadhatatlan. A Google Developers (2025) szerint az offline-first architektúra bevezetése 30%-kal növeli a felhasználói retenciót az instabil internettel rendelkező régiókban.
Főbb pontok
Offline Queue egy rendezett gyűjteménye a műveleteknek (létrehozás, frissítés, törlés), amelyeket az alkalmazás helyben tárol, amikor az eszköz nem fér hozzá a hálózathoz. Amint a kapcsolat helyreáll, a sor ugyanabban a sorrendben küldi el a műveleteket a szerverre, ahogy a felhasználó végrehajtotta őket.
Képzeljen el egy forgatókönyvet: egy üzenetküldő alkalmazás felhasználója üzeneteket gépel a metróban internet nélkül. Minden „Küldés” gomb megnyomása hozzáadódik az Offline Queue-hoz. Amikor a vonat kijön az alagútból és megjelenik a hálózat, az összes üzenet automatikusan elküldésre kerül. A felhasználói élmény zökkenőmentes: nem veszi észre, hogy offline volt, csak egy enyhe késést érez a küldés során.
A Uber Engineering (2024) szerint az offline soruk több mint 2 millió műveletet dolgoz fel naponta az alacsony kapcsolati minőségű régiókban. A sor a helyi Room tárolót használja FIFO sorrenddel és exactly-once garantált kézbesítési mechanizmussal.
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
)
Minden művelet tartalmazza az újraküldéshez szükséges összes adatot: endpoint, kérés törzse, időbélyeg és idempotencyKey. A Room adatbázis garantálja a sor megőrzését az alkalmazás újraindításakor és operációs rendszer összeomlásakor.
A kézbesítés garantálása a sor fő feladata. A felhasználónak biztosnak kell lennie abban, hogy a művelete (üzenet küldése, like, rendelés) végrehajtásra kerül, még akkor is, ha a hálózat nem érhető el a végrehajtás pillanatában. Az Offline Queue retry mechanizmussal eventually kézbesítést biztosít.
UX javítása gyenge kapcsolat mellett — a GSMA Mobile Economy Report (2025) szerint a világ mobilfelhasználóinak körülbelül 40%-a rendelkezik instabil internetkapcsolattal. Az Offline Queue használhatóvá teszi az alkalmazást a metróban, liftekben, távoli területeken — mindenhol, ahol a kapcsolat megszakadozik.
Adatveszteség csökkentése — sor nélkül az offline végrehajtott összes művelet elveszik. A felhasználó kitölthet egy hosszú űrlapot, megnyomhatja a „Küldés” gombot, és hálózati hibát láthat — az összes bevitt adat elvőszik. Az Offline Queue elmenti az adatokat, és az első adandó alkalommal elküldi őket. Az automatikus mentés a Google Docsban klasszikus példa az offline sorra dokumentumok esetében.
Aszinkron szinkronizálás — a sor lehetővé teszi az alkalmazás számára, hogy ne blokkolja a felületet a küldés idején. A felhasználó folytatja a munkát, míg a szinkronizáló kezelő a háttérben dolgozza fel a sort. Ez összhangban van a Reaktív Architektúra elveivel és javítja a felület érzékenységét.
A sor három rétege: tároló (persistence), ütemező (scheduler) és feldolgozó (executor). Tároló — Room QueuedOperation táblával. Ütemező — WorkManager (Android) vagy BGTaskScheduler (iOS), amely elindítja a szinkronizálást a hálózat megjelenésekor. Feldolgozó — egy szekvenciális FIFO iterátor, amely egyenként küldi el a műveleteket.
A feldolgozás sorrendje kritikus az adatok konzisztenciája szempontjából. Ha a felhasználó létrehozott egy rekordot, majd szerkesztette azt, mindkét műveletet ugyanabban a sorrendben kell elküldeni. Ellenkező esetben a szerver először egy nem létező rekord frissítését kapja — hiba. Sequential FIFO — szigorú sorrend a műveletek közötti függőségek ellenőrzésével.
Összevonási stratégia — ha a sorban egy objektumhoz CREATE és rögtön utána DELETE található, mindkét művelet törölhető küldés nélkül: a végállapot — az objektum nem jött létre. Hasonlóképpen, a CREATE + UPDATE CREATE összevonható egyetlen CREATE-vé a legújabb adatokkal. A sor optimalizálása csökkenti a HTTP-kérések számát és gyorsítja a szinkronizálást.
A Android Developers (2025) szerint a WorkManager az előnyös módszer az Offline Queue feldolgozására Androidon: garantálja a végrehajtást még az eszköz újraindítása után is, támogatja a hálózati elérhetőségre vonatkozó megszorításokat, és lehetővé teszi az újrapróbálkózási irányelv beállítását a NetworkType.CONNECTED segítségével.
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())
}
A CoroutineWorker műveletkötegeket dolgoz fel, és sikertelenség esetén Result.retry()-t ad vissza — a WorkManager automatikusan újraindítja a végrehajtást exponenciális késleltetéssel. Ez a legegyszerűbb mód egy megbízható Offline Queue létrehozására Androidon.
Exponential Backoff — a szabványos ismétlési stratégia növekvő időközzel: 2 mp, 4 mp, 8 mp, 16 mp és így tovább a maximális küszöbértékig. Ez megakadályozza a szerver túlterhelését, ha az átmenetileg nem érhető el. A Resilience4j (2024) Java könyvtár kész Retry implementációt kínál konfigurálható backoff-fal.
A próbálkozások maximális száma — kritikus paraméter. Ha 5–10 próbálkozás után a művelet nem sikerült, a további próbálkozások hiábavalóak. Dead letter queue javasolt: a próbálkozások kimerülése után a művelet átkerül egy külön táblába kézi elemzéshez. A Microsoft Patterns & Practices (2024) szerint a dead letter queue leegyszerűsíti a szinkronizációs problémák hibakeresését és megakadályozza a sor blokkolását hibás műveletek által.
Jitter — véletlenszerű változtatás — véletlenszerű szám hozzáadása a backoff intervallumhoz. Ha ezer eszköz egyszerre állítja helyre a kapcsolatot a megszakítás után, mindegyik egyszerre kezdi meg a szinkronizálást. A Jitter időben szétszórja őket, megakadályozva a Cache Stampede-t a szerveren. Teljes jitter: delay = random(0, backoff) — az AWS (2024) által ajánlott API ügyfelek számára.
Last Write Wins (LWW) — a legegyszerűbb stratégia: ütközés esetén az újabb időbélyeggel rendelkező művelet nyer. Az LWW időszinkronizációt igényel — a timestamp-et a szerveren kell generálni, vagy Logical Clock-ot (Lamport-órákat) kell használni. Hátrány: egy felhasználó adatai figyelmeztetés nélkül felülírásra kerülhetnek egy másik felhasználó adatai által.
OT (Operational Transformation) — a Google Docs által használt algoritmus valós idejű együttes szerkesztéshez, beleértve az offline módot is. Az OT útgy alakítja át a műveleteket, hogy azok a dokumentum bármely állapotára alkalmazhatóak legyenek, biztosítva a konzisztenciát blokkolás nélkül. CRDT (Conflict-Free Replicated Data Types) — az OT alternatívája, amely egyre népszerűbb a mobilalkalmazásokban: az adatok úgy vannak strukturálva, hogy az ütközések matematikailag megoldhatóak legyenek, központi szerver nélkül.
Egyedi összevonás — egyszerű adatmodellel rendelkező alkalmazásokhoz (jegyzetek, névjegyzékek) egyedi összevonási szabályok implementálhatók. Például egy jegyzet esetén: ha a szöveg két változatban módosult, egyesítse őket konkatenációként elválasztójellel. Felhasználó által megoldott konfliktus — ha az automatikus összevonás nem lehetséges, mutassa meg a felhasználónak mindkét verziót, és kínáljon választási lehetőséget. A Dropbox (2024) ezt a megközelítést használja az offline fájlokban keletkező konfliktusokhoz, és másolatokat hoz létre „Conflicted Copy” előtaggal.
Idempotency Key — a művelet egyedi azonosítója, amelyet a szerver a duplikált kérések észlelésére használ. Ha az ügyfél ugyanazt a kérést küldi el ugyanazzal a kulccsal, a szerver visszaadja a már végrehajtott művelet eredményét anélkül, hogy újra végrehajtaná. Ez kritikus fontosságú az Offline Queue számára, ahol az újraküldés hálózati hibák esetén előfordulhat.
Az idempotency key formátuma — UUID vagy a kérés paramétereinek hash-e. A szervernek tárolnia kell a végrehajtott kulcsokat az eredménnyel együtt egy ideig (általában 24 óráig) a duplikátumok észlelése érdekében. Stripe API (2024) — referencia példa: a kulcs az Idempotency-Key fejlécben kerül továbbításra, és az azonos kulccsal újraküldött kérések a gyorsítótárban tárolt választ adják vissza.
Generálás az ügyfél oldalán — a kulcs az ügyfélnél jön létre a művelet elküldése előtt, és a QueuedOperation táblában tárolódik. Újrapróbálkózáskor a kulcs nem változik. Exactly-once architektúra — az ügyfél oldali idempotency key és a szerver oldali deduplikáció kombinációja — az egyetlen mód annak garantálására, hogy egy művelet ne hajtódjon végre kétszer.
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()
)
Minden művelet két UUID-t kap: egyet — a rekord azonosítóját a sorban, a másikat — idempotency key-t a szerver számára. A szerver oldali deduplikáció idempotencyKey alapján garantálja, hogy még újraküldés esetén sem duplikálódik a rendelés.
Gyakran ismételt kérdések
A gyorsítótár (cache) adatmásolatokat tárol a gyors offline olvasáshoz. Az Offline Queue a felhasználói műveleteket tárolja a későbbi szerverre íráshoz. A cache olvasásra, a sor írásra működik. Mindkét összetevő együtt létezhet egy offline-first architektúrában.
Ajánlott korlát — 100–500 művelet. Több — a memória túlcsordulásának és a hosszú szinkronizálás kockázata a hálózat helyreállításakor. A korlát túllépésekor az alkalmazásnak figyelmeztetnie kell a felhasználót, és prioritásokat kell javasolnia a műveletekhez. Ésszerű korlátozás — 50 művelet frissítéshez + 10 létrehozáshoz.
A 7 napnál régebbi műveletek nulla sikerességgel átkerülnek a dead letter queue-ba. Elemezze őket kézileg: talán az API megváltozott, és az endpoint már nem létezik. Automatikus takarítás — egy HealthCheck feladat naponta egyszer törli vagy archiválja a lejárt műveleteket.
Használjon függőségi gráfot (DAG): minden művelet tartalmazza azon parentOperationId-k listáját, amelyeknek be kell fejeződniük a küldés előtt. A Room lekérdezés ORDER BY parent-tel a műveleteket a megfelelő sorrendben adja vissza. Kaszkád küldés — minden művelet befejezése után ellenőrizze, hogy a gyermek műveletek feloldásra kerültek-e.
Használja a Network Less Tool eszközt Android Emulatorban vagy a Network Link Conditioner eszközt iOS Simulatorban a hálózatvesztés szimulálására. Írjon teszteket, amelyek offline módban műveleteket adnak a sorhoz, helyreállítják a kapcsolatot, és ellenőrzik, hogy az összes művelet elküldésre és a szerver általi feldolgozásra került-e.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is