Как я вырубил всем пользователям синхронизацию

Как я на несколько часов отключил важную фичу, и узнал об этом почти случайно. Немного про тёмные углы App Engine и Cloud Firestore.

Как я вырубил всем пользователям синхронизацию

У меня в приложении есть суперфича - "cloud synchronization". Можно залогиниться в Гугл аккаунт, и редактировать ингредиенты-коктейли или добавлять элементы в "домашний бар" на одном устройстве, и в реальном времени видеть обновления на другом устройстве. Работает на Cloud Firestore. И хотя у меня к нему есть набор претензий, в целом все работает превосходно. Фича полезная, даже если второго устройства нет, просто это идеальный бэкап. Можно выбросить телефон, потом залогиниться на новом, и все коктейли будут на месте.

И вот недавно я случайно вывел эту синхронизацию из строя почти на сутки, даже не подозревая об этом. Про всю ситуацию можно написать нормальный такой корпоративный post-mortem, а у меня на хобби-проекте им вполне может служить пост в блоге. И я выделю основные моменты "Root cause" / "What went wrong", "Where we got lucky" и конечно же, "Action items".

В прошлом посте я писал, что у меня внезапно сломалось обновление сайта на App Engine, так что я захостил все статические ресурсы на прекрасном Firebase Hosting. Когда я убедился, что все работает, я решил отключить ставший совершенно ненужным App Engine.  Вот так это выглядит в настройках:

Что может пойти не так? Я нажал на кнопку и спокойно пошел спать. На самом деле, конечно, тут у меня все и сломалось в синхронизации. Это у нас будет непосредственный "Root cause", причина сбоя.

Череда везений

А дальше будут три момента, где мне повезло - "Where we got lucky". Первый момент смешной, мне написал пользователь с проблемой, причем, вроде как не связанной с синхронизацией. Первая часть письма была очень приятна, и я не могу не процитировать такую похвалу:

I want to first thank you for the amazing app. I tried every other clunky app that claimed "mixology master" but at best they were for the home bartender. Honestly MyBarApp is really the gold standard for industry professionals to stay organized and on top of things. When I was a new manager MBapp was like the Google Suite for the bar. Bravo.

Спасибо, добрый человек! Особенно приятно, когда приложение, рассчитанное (на самом деле) на домашний бар, оказывается полезным для профессиональной деятельности. Но дальше было самое интересное:

there is one issue: I paid for the Pro version back in 2018/2019 and had tons of recipes, lists, item entries of which was stored on an old phone. I was backing up my data but the "export data" function was brand new and I don't know what made all my information get lost.
How long do you keep app data on your end and is there anyway i can salvage my recipes? Even if the data is in text edit form or screenshots it would still work.

My email I used for the account is the same as this one (******@gmail.com), the phone number was ***-***-**** and I think my old password was *********.

Я, конечно, написал ему, что мне его номер телефона и пароли не нужны, и пожелал не разбазаривать их кому попало направо и налево (и на всякий случай сменить их поскорее). И естественно, я не полез проверять, подходит ли пароль для указанного аккаунта.

Но на созвоне с друзьями вечером следующего дня я пересказывал этот странный емэйл в саппорт и параллельно решил залезть в саму базу Firestore - проверить всё-таки, есть ли там вообще какие-то данные у его аккаунта. В Firebase веб консоли для этого есть удобный интерфейс, но когда я его открыл, то вместо привычного списка коллекций пользователей я увидел вот это:

Что это, божечки кошечки?!

Сказать, что у меня пригорело и я занервничал, это ничего не сказать. Хорошо, что во мне уже плескалось немного пива и вероятно, это помогло снизить всплеск адреналина. Моментально я включил обратно App Engine, попутно матеря эту нелепейшую невидимую зависимость и призывая всех богов, чтобы никакие данные не пропали. Сначала интерфейс Firestore не показывал мне вообще ничего из того, что там должно быть. Извините, слегка на нервах не сделал скриншоты этой драматичной пустоты. Но уже через пару минут все отобразилось, как надо, и я облегченно выдохнул.

То есть второй момент, где мне повезло, был в том, что Гугл не удалил к чертовой матери все данные у отключенного сервиса, а сохранил их на несколько часов.

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

И чуть не забыл - оказывается, разработчикам про это известно - вот замечательный вопрос на Stack Overflow. Вопрос, буквально, "зачем мне включать App Engine, если мне нужен Firestore". И ответ звучит примерно как "исторически сложилось, ничего сделать нельзя, не переписав кучу инфраструктуры".

Ох.

Ну раз ничего нельзя исправить, то можно в настройках App Engine хотя бы предупреждение небольшое сделать? Для таких наивных, как я, которые не подозревают о тайной связи Firestore и App Engine. Например, хотя бы вот так:

Что делать дальше

После включения App Engine обратно я проверил на своих телефонах, работает ли синхронизация. Всё работало прекрасно. Впопыхах я не догадался проверить функционал до включения App Engine, а экспериментировать с повторным сбоем как-то не вдохновляло.

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

До 5 марта число проблемных событий плавало в районе 10 в день, потом резкий всплеск до 150.

Что ж, могло быть и хуже!

Не знаю точную статистику, как часто люди включают синхронизацию, но учитывая, что для этого нужно логиниться в Google account или пойти в настройки, таких меньшинство. И я не получал больше сообщений о проблемах. То есть, скорее всего, клиентская часть Firestore пыталась тихонько себе подключаться к серверу, получала отлуп, но на работоспособности приложения локально это никак не отразилось. Можно записать такую надежность четвертым пунктом в части "повезло", но на самом деле это скорее продуманная устойчивость клиентской библиотеки (ну и моего кода тоже в некоторой степени) ко всякого рода сбоям.

А теперь главный Action item: настроить оповещения! Всякий мониторинг хорош только наполовину (а то и меньше), если серьезные изменения проходят незамеченными. Рассчитывать на то, что о проблемах сообщат пользователи - слишком плохо, доверие в таких ситуациях страдает невероятно. Если бы мне не написал человек с проблемами бэкапа, то кто его знает, сколько дней бы никакой синхронизации не происходило. Оповещение должно было сообщить мне о всплеске неприятных событий ну хотя бы на следующий день, когда логи предыдущего дня уже готовы к обработке. Про режим реального времени пока молчу, все-таки на частоте 10-150 событий в день нужно смотреть на окно как минимум несколько часов, чтобы не реагировать на разные флюктуации.

Более детально тему оповещений я пока не изучал. Похоже, они есть в Google Analytics, а не непосредственно в Firebase. Это не очень круто, но что поделать, придется заморочиться. Может быть, напишу об этом отдельно.

Cheers!

Loading comments...