Блог

Как сохранить чат живым, когда телефон спит

Агент Mythex может работать минутами над одним запросом, и вы вполне можете следить за ним с телефона, который блокируется, переключает приложения и меняет сеть во время работы. Две ошибки ломали это. В одной чат считал каждый сигнал «страница снова видна» доказательством того, что соединение умерло, и зацикливался, застряв на «Подключение…». В другой телефон, который проспал первый ответ нового чата, при возвращении показывал только первые несколько фрагментов ответа, пока страницу не обновят вручную. Обе ошибки исправлены.

Как чат следит за выполняющимся ходом

Пока агент работает, чат держит открытый поток с наших серверов: каждый шаг — мысль, вызов инструмента, фрагмент ответа — приходит как событие. Если поток обрывается, чат переподключается, а сервер воспроизводит недавние события из буфера, который хранит последние 120 секунд. Когда ход завершается, чат также запрашивает у сервера сохранённую историю и сверяет то, что показывал, с тем, что записано. Этот последний шаг ловит всё, что пропустил поток.

Чтобы отличить живое соединение от мёртвого, когда ничего не происходит, сервер отправляет небольшой «пинг» каждые 15 секунд.

Ошибка 1: пробуждение убивало здоровый поток

Браузеры сообщают странице, что она снова стала видимой: после переключения вкладки, после разблокировки экрана. Мы использовали это как повод проверить соединение — и на практике прерывали поток и переподключались, предполагая, что он умер, пока страница была скрыта.

На телефонах и во встроенных браузерах эти события срабатывают гораздо чаще, чем умирают потоки: при каждом переключении вкладки, каждой разблокировке, а в некоторых встроенных браузерах каждые пару секунд. Каждое такое событие прерывало совершенно здоровый поток. Чат переподключался, воспроизводил события, снова прерывался и в итоге зависал на «Подключение…». Потом он сообщал, что ход завершён, хотя агент всё ещё работал.

Исправление: судить о потоке по тому, говорит ли он

Теперь чат записывает, когда поток каждого проекта в последний раз получил хоть что-нибудь — и события, и 15-секундные пинги. Сигнал «снова видна» прерывает поток, только если он молчит 25 секунд: дольше интервала пингов плюс задержки медленной сети, поэтому живой поток никогда под это не попадает. Тесты проверяют, что пинг считается признаком жизни и что поток, который только что пинговал, не считается мёртвым.

Правило, которое мы вынесли: видимость страницы говорит о странице, а не о сетевом соединении. Спрашивайте само соединение.

Ошибка 2: половина ответа после пробуждения телефона

Эту ошибку мы могли воспроизвести каждый раз в симуляторе iOS:

  1. Начните новый чат и отправьте запрос, который занимает время.
  2. Дайте телефону уснуть во время сборки.
  3. Вернитесь, когда ход уже завершился и двухминутный буфер повтора истёк.

Чат показывал первые несколько блоков ответа, помеченных как завершённые, — и так оставался до обновления страницы.

Почему

Новый чат не имеет ветки — сохранённой переписки — до тех пор, пока первое сообщение её не создаст. Это происходит внутри функции отправки, после того как отправка уже захватила шаг сверки, который всё ещё считал, что ветки нет. Поэтому в конце первого хода в новом чате сверка не видела ветки и тихо возвращалась, ничего не запрашивая.

Обычно этого никто не замечал, потому что поток доставлял весь ход целиком. Но телефон, который проспал ход и вернулся уже после того, как буфер повтора на 120 секунд истёк, не мог получить пропущенные события из потока — а сверка, которая должна была заполнить пробел, так и не запустилась.

Исправление

  • Отправка сообщает сверке, какой ветке принадлежит ход, поэтому первый ход нового чата сверяется так же, как любой другой. Если к моменту прихода ответа вы открыли другой чат, результат отбрасывается, а не показывается не в том месте.
  • Неудачная сверка повторяется. Телефон, который просыпается на плохом соединении, может обнаружить, что ход уже завершился, и не смочь его получить. Теперь это запоминается, и чат спрашивает снова, когда вкладка снова становится видимой или сеть возвращается.
  • «Работал» — честная цифра. Каждый ответ показывает, сколько агент работал. Если вкладка не видела сообщения сервера о завершении хода, раньше она заполняла это по собственным часам, которые шли от момента отправки до пробуждения телефона, включая время отсутствия. Теперь эта цифра помечается как оценка и заменяется сохранённой длительностью, как только придёт история.

Что мы из этого вынесли

  • Тестируйте на том устройстве, которое люди реально используют, и так, как они его используют. Обе ошибки жили в зазоре между «поток, который работает» и «телефон в кармане».
  • Резервный механизм, который никогда не запускается, не является резервным. Сверка существовала именно для этого случая и молча его пропускала.
  • Повторяйте и восстановление. Момент, когда телефон просыпается, часто совпадает с худшим состоянием его соединения.
  • Не показывайте догадку как факт. Длительность, измеренная по неверным часам, хуже, чем никакой; пометьте её или замените.

В той же работе были и другие улучшения, которые вы увидите во время выполнения хода: шаги командной оболочки подписываются по команде, которая выполняет работу, а не по cd; скриншоты в чате сохраняют верхний левый угол страницы и помещаются в колонку; новый проект получает сгенерированное имя без обновления страницы.

Если вы строите собственное приложение для телефонов, наши руководства о создании мобильного веб-приложения и нативных приложениях и прогрессивных веб-приложениях покрывают основы. Больше о самом чате — в документации по чату.

Mythex · Pricing · Создавайте что угодно с ИИ · Шаблоны сайтов и приложений · Сравнения Mythex · Глоссарий по созданию приложений с ИИ · Бесплатные инструменты для создания приложений с ИИ · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)