Чатът остава жив, когато телефонът заспи
Агентът на Mythex може да работи няколко минути по една заявка, а вие може да следите от телефон — който се заключва, сменя приложенията и мрежите, докато работи. Два бъга объркваха това. При единия чатът третираше всеки сигнал „страницата е видима отново“ като доказателство, че връзката му е умряла, и зацикляше на „Connecting…“. При другия телефон, който беше заспал през първия отговор на нов чат, се връщаше само с първите няколко части от него, докато не се презареди ръчно страницата. И двата са поправени.
Как чатът следи работещ ход
Докато агентът работи, чатът държи отворен поток от нашите сървъри: всяка стъпка — мисъл, извикване на инструмент, част от отговора — пристига като събитие. Ако потокът прекъсне, чатът се свързва отново и сървърът повтаря скорошните събития от буфер, който пази последните 120 секунди. Когато ходът завърши, чатът също пита сървъра за запазената история и съгласува това, което е показал, с това, което е записано. Тази последна стъпка улавя всичко, което потокът е пропуснал.
За да разбере дали връзката е жива, когато нищо не се случва, сървърът изпраща малко „ping“ на всеки 15 секунди.
Бъг 1: събуждането убиваше здрав поток
Браузърите казват на страницата, когато тя стане видима отново: след смяна на таб, след отключване на екрана. Използвахме това като сигнал да проверим връзката — и на практика да прекъснем потока и да се свържем отново, при предположение, че е умрял, докато е бил скрит.
На телефони и във вградени браузъри тези събития се случват далеч по-често от това, че потоците умират — при всяка смяна на таб, при всяко отключване, а в някои вградени браузъри на всеки няколко секунди. Всяко от тях прекъсваше напълно здрав поток. Чатът се свързваше отново, повтаряше, прекъсваше пак и накрая стоеше на „Connecting…“. После казваше, че ходът е приключил, макар агентът още да работи.
Решението: преценяване на потока по това дали говори
Чатът вече записва кога потокът на всеки проект за последен път е получил каквото и да е — събития и 15-секундните ping-ове. Сигналът „видим отново“ прекъсва поток само ако е мълчал 25 секунди: повече от интервала на ping плюс бавен мрежов скок, така че жив поток никога не попада в този случай. Тестовете проверяват, че ping се брои като признак на живот и че поток, който току-що е пингувал, не се третира като мъртъв.
Правилото, което извлякохме: видимостта на страницата казва нещо за страницата, а не за мрежовата връзка. Питайте връзката.
Бъг 2: половин отговор след като телефонът се събуди
Този можехме да възпроизведем всеки път в iOS симулатора:
- Започнете нов чат и изпратете заявка, която отнема известно време.
- Оставете телефона да заспи през билда.
- Върнете се, след като ходът е приключил и двуминутният буфер за повторение е изтекъл.
Чатът показваше първите няколко блока на отговора, маркирани като завършени — и оставаше така, докато не презаредите страницата.
Защо
Нов чат няма нишка — запазената разговорна история — докато първото съобщение не я създаде. Това се случва вътре във функцията за изпращане, след като изпращането вече е запазило стъпката за съгласуване, която все още мислеше, че няма нишка. Затова в края на първия ход в нов чат съгласуването не виждаше нишка и тихо се връщаше, без да иска нищо.
Обикновено никой не забелязваше, защото потокът вече беше доставил целия ход. Но телефон, който беше заспал през целия ход и се беше върнал след като буферът за повторение от 120 секунди е изтекъл, не можеше да получи липсващите събития от потока — а съгласуването, което трябваше да запълни празнината, така и не се беше изпълнило.
Решението
- Изпращането казва на съгласуването към коя нишка принадлежи ходът, така че първият ход в нов чат се съгласува като всеки друг. Ако сте отворили друг чат, докато отговорът пристигне, резултатът се отхвърля, вместо да се покаже на грешното място.
- Неуспешното съгласуване се опитва пак. Телефон, който се събужда на лоша връзка, може да открие, че ходът е приключил, но да не успее да го изтегли. Това вече се запомня и чатът пита отново, когато таба се покаже пак или мрежата се върне.
- „Worked for“ е честно. Всеки отговор показва колко време е работил агентът. Ако табът никога не е видял края на хода от сървъра, той го допълваше от собствения си часовник — който тръгваше от Send до събуждането на телефона, включително времето далеч. Тази стойност вече е маркирана като оценка и се заменя със запазената продължителност, щом историята пристигне.
Какво взехме от това
- Тествайте на устройството, което хората наистина използват, по начина, по който го използват. И двата бъга живееха в празнината между „поток, който работи“ и „телефон в джоб“.
- Резервен вариант, който никога не се изпълнява, не е резервен вариант. Стъпката за съгласуване съществуваше точно за този случай и тихо го пропускаше.
- Опитвайте отново и възстановяването. Моментът, в който телефонът се събужда, често е моментът, в който връзката му е най-слаба.
- Не показвайте предположение като факт. Продължителност от грешен часовник е по-лоша от никаква; маркирайте я или я заменете.
Същата работа изчисти и някои неща, които ще видите, докато ходът работи: стъпките в терминала се означават с командата, която върши работата, а не с cd; скрийншотите в чата запазват горния ляв ъгъл на страницата и се побират в колоната; а новият проект взима генерираното си име без презареждане.
Ако създавате собствено приложение за телефони, нашите ръководства за създаване на уеб приложение, удобно за мобилни и native срещу progressive web apps обхващат основите. Повече за самия чат има в документацията за чата.