Menținerea chatului activ când telefonul intră în repaus
Agentul Mythex poate lucra minute întregi la o singură cerere, iar tu s-ar putea să urmărești de pe telefon — care se blochează, schimbă aplicațiile și trece de pe o rețea pe alta în timp ce lucrează. Două erori făceau ca lucrurile să meargă prost. Într-una, chatul trata fiecare semnal „pagina este din nou vizibilă” drept dovadă că legătura lui murise și intra în buclă până rămânea blocat pe „Se conectează…”. În cealaltă, un telefon care dormise peste primul răspuns al unui chat nou revenea cu doar primele câteva bucăți din răspuns, până la o reîmprospătare manuală. Ambele sunt reparate.
Cum urmărește chatul o tură în desfășurare
Cât timp agentul lucrează, chatul ține deschis un stream de la serverele noastre: fiecare pas — o gândire, un apel de instrument, o bucată din răspuns — sosește ca eveniment. Dacă stream-ul se întrerupe, chatul se reconectează, iar serverul redă evenimentele recente dintr-un buffer care păstrează ultimele 120 de secunde. Când tura se termină, chatul cere serverului și istoricul salvat și reconciliază ce a arătat cu ce a fost stocat. Acest ultim pas prinde orice a ratat stream-ul.
Ca să deosebească o conexiune vie de una moartă când nu se întâmplă nimic, serverul trimite un mic „ping” la fiecare 15 secunde.
Eroarea 1: trezirea omora un stream sănătos
Browserele anunță o pagină când redevine vizibilă: după schimbarea unei file, după deblocarea ecranului. Noi foloseam asta ca semnal să verificăm conexiunea — de fapt, să anulăm stream-ul și să ne reconectăm, presupunând că murise cât era ascuns.
Pe telefoane și în browserele încorporate, aceste evenimente se declanșează mult mai des decât mor stream-urile — la fiecare schimbare de filă, la fiecare deblocare și, în unele browsere încorporate, aproape la fiecare câteva secunde. Fiecare dintre ele anula un stream perfect sănătos. Chatul se reconecta, redă, era anulat din nou și ajungea să stea pe „Se conectează…”. Apoi spunea că tura s-a încheiat, deși agentul încă lucra.
Soluția: judecă stream-ul după faptul că vorbește
Chatul înregistrează acum când a primit ultima dată ceva fiecare stream al unui proiect — evenimente și ping-urile de 15 secunde deopotrivă. Un semnal „din nou vizibil” anulează un stream doar dacă a fost tăcut 25 de secunde: mai mult decât intervalul de ping plus un salt lent de rețea, deci un stream viu nu se califică niciodată. Testele verifică faptul că un ping contează drept semn de viață și că un stream care tocmai a trimis un ping nu este tratat ca mort.
Regula pe care am extras-o: vizibilitatea unei pagini spune ceva despre pagină, nu despre conexiunea de rețea. Întreabă conexiunea.
Eroarea 2: jumătate de răspuns după ce telefonul s-a trezit
Aceasta am putut-o reproduce de fiecare dată în simulatorul iOS:
- Pornește un chat nou și trimite o cerere care durează.
- Lasă telefonul să intre în repaus în timpul construcției.
- Revino după ce tura s-a terminat și bufferul de redare de două minute a expirat.
Chatul arăta primele câteva blocuri ale răspunsului, marcate ca terminate — și rămânea așa până la o reîmprospătare a paginii.
De ce
Un chat nou nu are încă un fir — conversația stocată — până când primul mesaj creează unul. Asta se întâmplă în interiorul funcției de trimitere, după ce trimiterea capturase deja pasul de reconciliere, care încă credea că nu există fir. Deci, la sfârșitul primei ture dintr-un chat nou, reconcilierea nu vedea niciun fir și revenea fără să ceară nimic.
De obicei nimeni nu observa, pentru că stream-ul livrase oricum întreaga tură. Dar un telefon care dormise peste tură și revenise după ce bufferul de redare de 120 de secunde expirase nu putea primi evenimentele lipsă de la stream — iar reconcilierea care trebuia să umple golul nu rulase niciodată.
Soluția
- Trimiterea îi spune reconcilierii ce fir aparține turei, astfel încât prima tură a unui chat nou să fie reconciliată ca oricare alta. Dacă între timp ai deschis alt chat până să sosească răspunsul, rezultatul este aruncat în loc să fie afișat în locul greșit.
- O reconciliere eșuată este reîncercată. Un telefon care se trezește pe o conexiune proastă poate descoperi că tura s-a terminat și apoi nu reușește s-o aducă. Acum asta este reținut, iar chatul întreabă din nou când fila este afișată din nou sau când revine rețeaua.
- „Lucrat timp de” este onest. Fiecare răspuns arată cât a lucrat agentul. Dacă fila nu a văzut niciodată mesajul de sfârșit de tură de la server, înainte completa acea durată din propriul ceas, care mergea de la Trimitere până când telefonul s-a trezit, inclusiv timpul în care fusese plecat. Acum cifra este marcată ca estimare și înlocuită cu durata stocată de îndată ce sosește istoricul.
Ce am învățat
- Testează pe dispozitivul pe care oamenii îl folosesc de fapt, în modul în care îl folosesc. Ambele erori trăiau în spațiul dintre „un stream care funcționează” și „un telefon în buzunar”.
- O soluție de rezervă care nu rulează niciodată nu este o soluție de rezervă. Pasul de reconciliere exista tocmai ca să prindă acest caz, și îl sărea în tăcere.
- Reîncearcă și recuperarea. Momentul în care se trezește un telefon este adesea și cel în care conexiunea lui este în cea mai proastă stare.
- Nu prezenta o estimare drept fapt. O durată măsurată cu ceasul greșit este mai rea decât niciuna; etichetează-o sau înlocuiește-o.
Aceeași lucrare a rezolvat și câteva lucruri pe care le vei vedea în timpul unei ture: pașii de shell sunt etichetați după comanda care face lucrul, nu după cd, capturile de ecran din chat păstrează colțul din stânga-sus al paginii și se încadrează în coloană, iar un proiect nou își preia numele generat fără reîmprospătare.
Dacă îți construiești propria aplicație pentru telefoane, ghidurile noastre despre cum construiești o aplicație web prietenoasă cu telefonul și aplicații native vs. aplicații web progresive acoperă elementele de bază. Mai multe despre chatul în sine găsești în documentația chatului.