Preskoči na glavni sadržaj
Offline-first design for a mobile SaaS app, showing sync queues and conflict rules

Offline-first arhitektura u mobilnom SaaS-u: sinhronizacija i pravila za konflikte

Offline-first dizajn drži mobilnu SaaS aplikaciju korisnom bez mreže. Pogledajte kako se slažu lokalno skladište, red čekanja, idempotentni API-ji i pravila za konflikte.

Sadržaj

Mobilna SaaS aplikacija stalno gubi signal. Telefon ulazi u lift, u podrum ili u voz. Zato takva aplikacija mora raditi i kad mreža padne. Korisnici i dalje traže svoje podatke. Uz to, žele da završe zadatak koji je pred njima.

Aplikacija te izmjene može poslati kasnije, čim se signal vrati. Kao rezultat, proizvod djeluje pouzdano, a ne krhko. To smanjuje i nervozu koju slaba mreža stvara.

Za timove koji grade mobilna SaaS rješenja, rad van mreže nije dodatna pogodnost. Umjesto toga, on pripada dizajnu od prvog dana.

Šta znači offline-first

Offline-first dizajn tretira telefon kao pravi dom za podatke. Umjesto da zove server na svaki dodir, aplikacija zadržava ono što joj treba na uređaju. Prvo čita iz lokalnog skladišta. Zatim razgovara sa serverom kad mreža to dozvoli.

To okreće uobičajeni odnos između aplikacije i njenog bekenda. Server ostaje glavni, međutim uređaj može stajati sam za brojne zadatke.

Model dobro pristaje mobilnom SaaS proizvodu, jer mobilni korisnici žive sa isprekidanim signalom. Na primjer, aplikacije otvaraju u vozu, u liftu, u podrumu ili u prepunoj sali.

Obična aplikacija prikaže indikator učitavanja čim signal padne. Mobilna SaaS aplikacija sa offline-first dizajnom i dalje prikazuje keširane podatke i prima unos. Ta razlika je važna, jer ljudi sude o softveru po tome kako se ponaša na težak dan.

Zašto mobilna SaaS aplikacija traži rad van mreže

Mobilna SaaS aplikacija nosi posao koji niko ne može odložiti. Prodavci, vozači, terenski inženjeri i ekipe na gradilištu cijeli dan zavise od uređaja. Mrtva tačka prekida taj tok u najgorem trenutku. Korisnici tada gube ono što su ukucali, ili ponavljaju korak jer ne vide rezultat.

Offline-first dizajn odvaja ponašanje aplikacije od stanja mreže. Aplikacija prima izmjenu sada, a šalje je kasnije. I brzina raste, pošto se lokalni podaci pojave odmah.

Model ipak donosi nove probleme. Tim mora odlučiti koji podaci žive na uređaju, kako se izmjene redaju i kako teče sinhronizacija. Najteže pitanje je konflikt: telefon i server mogu mijenjati isti zapis dok su razdvojeni.

Lokalno skladište je temelj

Lokalno skladište je temelj svake offline-first aplikacije. Ono pušta telefon da drži uredne, tipizirane podatke bez poziva serveru. Za većinu proizvoda mala baza pobjeđuje običan skup ključeva i vrijednosti. Baza mnogo olakšava upite, indekse, veze između zapisa i velike skupove.

SQLite je čest izbor na mobilnim uređajima. To je mali relacioni motor koji sjedi baš na uređaju, a tim iza njega jasno opisuje gdje taj motor pristaje i gdje ne.

Timovi mogu keširati zapise koje korisnici najviše diraju. Aplikacija ih onda čita bez ijednog zahtjeva. Lokalni upisi rade na isti način. Korisnik može dodati ili urediti zapis van mreže, a aplikacija tu izmjenu zadržava dok sinhronizacija ne krene.

Izbor onoga što ostaje na uređaju

Offline-first ne znači kopiranje cijelog bekenda na svaki telefon. Takav pristup troši prostor i diže rizik po privatnost.

Umjesto toga, izaberite podatke koji korisnicima stvarno trebaju dok su odsječeni. U većini aplikacija to znači skorašnje zapise, otvorene zadatke, osnovne podatke o nalogu i ono što traži trenutni posao.

Politike keša mogu se razlikovati po kategoriji. Na primjer, vrući zapisi mogu ostati sedmicama, dok rijetki brzo ispadaju. Osjetljivi redovi traže dodatnu pažnju, jer je uređaj sada još jedno mjesto gdje sjede poslovni podaci. I stari redovi treba da isteknu, da lokalno skladište ne raste bez granice.

Red čekanja za akcije van mreže

Lokalni podaci rješavaju tek pola problema. Aplikacija traži i pouzdan način da drži akcije napravljene van mreže. Red čekanja radi taj posao. Umjesto da odmah ispali API poziv, aplikacija upisuje akciju u lokalnu listu.

Na primjer, korisnik uređuje zapis o kupcu van mreže. Aplikacija čuva izmjenu i dodaje stavku za sinhronizaciju u red čekanja. Zatim, kad se signal vrati, prolazi kroz listu po redu.

Svaka stavka treba da nosi dovoljno detalja da se akcija ponovi: tip, identifikator zapisa, sadržaj, vremensku oznaku i jedinstveni id.

Red čekanja traži i ponovne pokušaje, jer kratak prekid mreže ne smije baciti korisnikovu akciju. Ipak, ponovni pokušaji dižu novi rizik. Konkretno, isti poziv poslat dvaput može stvoriti duple zapise.

Zašto su idempotentni API-ji važni

Idempotentan poziv daje isti rezultat bez obzira na to koliko puta se izvrši. To svojstvo postaje presudno čim uređaj krene sa ponovnim pokušajima.

Na primjer, uzmite aplikaciju koja pravi narudžbu van mreže. Ona se ponovo poveže i pošalje poziv, ali veza padne prije nego što odgovor stigne. Aplikacija ne može znati da li je server primio narudžbu. Zato mora pokušati ponovo.

Bez zaštite, taj ponovni pokušaj pravi drugu narudžbu. Sa idempotentnom krajnjom tačkom, server prepoznaje prvi poziv i vraća isti rezultat. Jedinstveni identifikator akcije sa klijenta je uobičajena zaštita. Server čuva taj id uz zapis koji je napravio.

HTTP ima ime za to svojstvo, a RFC 9110 nabraja koji ga metodi nose. Obrazac pomaže daleko izvan rada van mreže. Uz to, štiti i obične pozive na klimavoj vezi. Za mobilni SaaS, idempotencija pripada dizajnu API-ja od početka, a ne kasnijoj zakrpi.

Dizajn ciklusa sinhronizacije

Sinhronizacija spaja lokalno skladište sa istinom na serveru. Ona traži izričite politike za ono što se dešava kad se uređaj vrati.

Prost ciklus počinje kad aplikacija vidi živu vezu. Onda gura lokalne akcije na čekanju, a poslije toga povlači svježe podatke sa servera. Redoslijed zavisi od poslovnih pravila. Neki timovi prvo guraju, dok drugi prvo povlače.

Bitno je da ciklus radi isto svaki put. Predvidiv proces tim može testirati na brojne načine kvara.

Sinhronizacija nikad ne smije pretpostaviti stabilnu vezu. Na primjer, telefon može držati signal nekoliko sekundi, pa opet pasti. Zbog toga sinhronizacija treba da radi u malim serijama. Aplikacija može označiti svaku seriju koja prođe, a sve što padne čeka sljedeći pokušaj.

Kad se klijent i server sukobe

Najteži dio offline-first pristupa izlazi na vidjelo kad se dvije kopije jednog zapisa promijene odvojeno.

Na primjer, uzmite terenskog inženjera i menadžera u kancelariji. Inženjer mijenja broj telefona kupca van mreže. U međuvremenu menadžer mijenja isti taj broj u veb aplikaciji. Obje izmjene su ispravne, a sistem ipak mora izabrati ishod u trenutku sinhronizacije.

To je konflikt, i pravila za njega pripadaju dizajnu prije lansiranja. Najprostija politika je pobjeda posljednjeg upisa: najnovija izmjena po satu ili verziji uzima zapis. Lako je shvatiti, međutim prave izmjene mogu nestati.

Spajanje po poljima je blaže. Ako jedan korisnik mijenja broj telefona, a drugi adresu, aplikacija može zadržati oba. Neki tokovi traže čovjeka. Na primjer, aplikacija može prikazati obje verzije i pustiti korisnika od povjerenja da izabere.

Nijedna politika ne pristaje svakom mobilnom SaaS proizvodu. Ispravna prati poslovni proces, pa prvo mapirajte taj proces.

Verzije i praćenje izmjena

Brojevi verzija čine sinhronizaciju daleko lakšom za razumijevanje. Svaki zapis na serveru nosi verziju koja se pomjera na svaku izmjenu. Klijent šalje verziju koju je posljednju vidio. Server onda provjerava da li je ta verzija još aktuelna.

Ako se dvije poklope, upis prolazi. Ako se razlikuju, server zna da je druga izmjena stigla prva. Ta zaštita sprječava tiha prepisivanja.

Još jedna korisna tehnika je praćenje pojedinačnih izmjena umjesto cijelih zapisa. Klijent šalje akciju, a ne cio objekat. Time smanjuje izglede da pregazi izmjene koje nikad nije vidio. Ostaje i jasan trag o tome šta je koji uređaj pokušao.

Dizajn za slab signal

Offline-first je više od mrtve veze. Većina korisnika trpi slab signal mnogo češće nego potpuni prekid.

Telefon može cijeli dan skakati između Wi-Fi i mobilne mreže. Veza može i odgovoriti, ali odgovoriti vrlo sporo. Zato aplikacije treba da izbjegnu blokiranje ekrana na svaki poziv. Ovdje su bitni i tajmauti, pošto nijedan zahtjev ne smije zamrznuti prikaz dok aplikacija čeka.

Interfejs treba da kaže status sinhronizacije običnim riječima. Korisnici treba da znaju da li aplikacija drži izmjenu na uređaju, čeka u redu ili je dobila potvrdu servera. Jasan status sprječava ljude da stalno lupaju isto dugme.

I zastavice mreže su slab izvor istine. Uređaj može tvrditi da ima živu vezu dok server ostaje nedostupan. MDN ističe baš tu ogradu u svojim bilješkama o svojstvu online. Zbog toga pravi odgovor API-ja tretirajte kao jači signal.

Kad sinhronizacija padne

Sinhronizacija može pasti iz brojnih razloga. Server može odbiti akciju. Veza može pući. Podaci možda više ne odgovaraju važećim pravilima.

Ne zaslužuje svaki kvar isti odgovor. Kratka mrežna greška može ostati u redu čekanja. Međutim, trajna greška traži drugačiji tretman. Na primjer, server može odbiti izmjenu jer je korisnik izgubio pravo na taj zapis. Vječito ponavljanje tog poziva ne pomaže nikome. Aplikacija treba da ga označi i objasni običnim riječima.

I djelimična sinhronizacija zaslužuje pažnju. Ako deset akcija čeka, a sedma padne, aplikacija treba da zna status svake. Status po akciji čuva red čekanja od pretvaranja u jednu veliku nepoznanicu.

SQLite, WatermelonDB i motor za sinhronizaciju

SQLite ostaje čvrst izbor za tipizirane lokalne podatke. Njegov relacioni model pristaje zapisima, vezama, upitima i sigurnim upisima. Tim može graditi sloj sinhronizacije pravo na njemu. Takav pristup daje punu kontrolu, ali stavlja i više posla na tim.

WatermelonDB je druga opcija za React Native aplikacije koje žele bogatiji lokalni sloj. Cilja na local-first ponašanje i reaktivno čitanje, a projekat živi otvoreno na GitHubu.

Nijedna baza sama ne pravi offline-first dizajn. Timovima i dalje trebaju pravila sinhronizacije, red čekanja, rješavanje konflikata i ispravno ponašanje API-ja.

Kako aplikacija raste, sinhronizacija često zaslužuje svoj sloj. Motor za sinhronizaciju prati akcije na čekanju i odlučuje kad se izvršavaju. On drži i ponovne pokušaje, provjere verzija i odgovore na konflikte. Držite ga odvojeno od pojedinih ekrana, jer inače svaka funkcija dobije svoju kopiju. Jedan motor je lakše testirati, pošto tim može simulirati prekinute veze, ponovljene pozive i konflikte.

Testiranje i nadzor

Mobilna SaaS aplikacija traži testove van mreže koji oponašaju stvarni život. Na primjer, presijecite vezu usred sinhronizacije. Pošaljite istu akciju dvaput. Uredite isti zapis na dva mjesta. Ugasite aplikaciju dok je red čekanja pun.

Ti testovi otkrivaju kvarove koje testiranje na mreži rijetko pokaže. Uz to, grade povjerenje da će aplikacija izdržati na terenu.

Poslije lansiranja timu i dalje trebaju oči na sinhronizaciji. Korisne mjere su stopa uspjeha, broj ponovnih pokušaja, veličina reda, stopa konflikata i vrijeme sinhronizacije. Red koji raste može ukazati na kvar bekenda ili na grešku u sinhronizaciji. Slično, skok konflikata može otkriti promjenu u načinu na koji ljudi rade. Logovi treba da nose dovoljno detalja za praćenje kvara, a da izostave lične podatke.

Česte greške

Česta greška je tretirati rad van mreže kao problem keširanja. Keš može prikazati stare podatke, ali ne prima upise.

Druga je slanje cijelih zapisa pri sinhronizaciji, što gazi izmjene napravljene drugdje. Treća je ponavljanje poziva bez ikakve idempotencije. Četvrta je vjerovanje satovima na uređajima, pošto oni odlaze i ne slažu se.

Na kraju, brojni timovi kače podršku za rad van mreže na sam kraj. Do tada logika aplikacije svuda zavisi od živih poziva. Rano planiranje rada van mreže čuva dizajn čistim i smanjuje kasnije prepravke.

Kako Square gradi mobilna SaaS rješenja

Square Software gradi sopstvene softverske proizvode i prima outsourcing poslove za timove kojima treba pouzdana mobilna SaaS aplikacija. Naše cijene idu 35-55 EUR na sat. Ista pravila važe kroz cio stek: lokalno skladište, dizajn API-ja, tok sinhronizacije i rješavanje konflikata.

Partner može pomoći da se postavi temelj prije nego što rad van mreže postane težak za dodavanje. Ukratko, to znači izbor lokalnog skladišta, oblikovanje otpornih API-ja, skicu ciklusa sinhronizacije i dogovor o politikama za konflikte. Možete procijeniti cijenu izrade ili nam se javiti da o tome popričamo.

Zaključak

Offline-first dizajn drži mobilnu SaaS aplikaciju korisnom kad mreža padne. On spaja lokalno skladište, red čekanja, idempotentne API-je, ciklus sinhronizacije i jasna pravila za konflikte.

SQLite i WatermelonDB daju lokalni temelj. Redovi čekanja drže korisničke akcije dok server ne postane dostupan. Idempotentne krajnje tačke sprječavaju da ponovni pokušaji udvostruče zapise. Na kraju, verzije i politike spajanja vraćaju obje strane u red.

Rezultat je više od režima van mreže. To je mobilna SaaS aplikacija napravljena za način na koji mobilne mreže stvarno rade. Za posao, ta pouzdanost se vidi kao povjerenje, i kao posao koji se nikad ne gubi.

Spremni da pokrenete svoj projekat?

Razgovarajmo o tome kako možemo pomoći da oživite svoje ideje uz softverska rješenja po mjeri.

Kontaktirajte nas