Ловимо застосунки, які падають одразу після публікації
25 вересня три публікації були позначені як успішні, хоча API застосунку падав за кілька секунд після кожного запуску. Оскільки вони «пройшли», відкат не запускався; фонова перевірка провалила їх через кілька хвилин, і весь сайт перейшов у стан 404. Перевірка працездатності рахувала збої у списку подій хостинг-платформи — а той тримає лише останні п'ять подій на машину, тож цикл падінь постійно заповнює його, і лічильник ніколи не зростає. Тепер вона порівнює час найновішого збою, і публікація з циклічними падіннями провалюється та відновлює попередню версію.
Чого чекає публікація
Коли ви публікуєте застосунок із бекендом на Mythex, нова версія розгортається на машинах нашої хостинг-платформи, а перевірка працездатності вирішує, чи публікація стала активною, чи провалилася. Якщо вона провалилася, відкат повертає попередню версію.
Складність у тому, що «запущено» не означає «обслуговує». Платформа позначає машину як запущену, щойно вона піднялася. Застосунок, який падає за секунду після запуску, одразу перезапускається, і за мить знову виглядає запущеним. Тому перевірка працездатності з часом обросла кількома шарами:
- Дивитися двічі. Після того як машина позначена як запущена, почекати трохи і подивитися знову. Падіння під час запуску часто провалює другу перевірку.
- Стежити за циклічними падіннями. Якщо платформа повідомляє, що машина падала знову і знову і вона припинила її перезапускати, провалити.
- Рахувати збої з моменту початку публікації. Два погляди «запущено» можуть охоплювати перезапуск. Тож якщо від початку цієї публікації був будь-який збій, дивитися втретє; якщо збоїв більше, ніж при попередньому погляді, застосунок не тримається стабільно.
Третя перевірка саме і провалилася.
Чому лічильник не зростав
Інформація про збої надходить зі списку подій кожної машини: запуски, завершення, перезапуски. Платформа зберігає лише останні п'ять подій на машину.
Уявіть застосунок, який падає через 2,5 секунди після кожного запуску, як і один із них. Кожен цикл додає збій і запуск. Через пару циклів список заповнюється. Відтоді кожна нова подія витісняє одну стару. Список зсувається вперед, але завжди містить приблизно те саме співвідношення: пару збоїв і пару запусків.
Тож «скільки збоїв з моменту початку публікації» щоразу давало те саме число. Другий погляд бачив, скажімо, два збої. Третій погляд теж бачив два — інші збої, але та сама кількість. Перевірка зробила висновок, що падіння припинилися, і пропустила публікацію.
Так сталося тричі 25 вересня, на двох застосунках. Щоразу:
- публікацію позначали як активну,
- відкат не запускався, бо нічого не провалилося,
- наш reconciler, фонова задача, яка перевіряє розгортання постфактум, провалював розгортання через кілька хвилин,
- і весь сайт повертав 404.
Публікація, що провалюється вчасно, відновлювана: відкат повертає попередню версію. Публікація, яка провалюється через кілька хвилин після того, як її оголосили успішною, вже пропустила свій відкат.
Як ми це знайшли
Ми відтворили це локально: взяли робочий API, дали йому заснути, а потім перепублікували його зі змінами, які падали під час запуску. Перевірка працездатності позначила його як активний.
Це збіглося з продакшеном: у кожній із трьох публікацій застосунок помирав за секунди після кожного запуску, але лічильник збоїв, який порівнювала перевірка, між поглядами ніколи не зростав.
Виправлення: порівнювати найновіший збій, а не кількість
Замість підрахунку збоїв перевірка тепер дивиться на час найновішого збою з моменту початку публікації.
Якщо другий погляд показує будь-який збій після початку публікації, перевірка чекає і дивиться втретє. Якщо найновіший збій на третьому погляді пізніший, ніж найновіший на другому, машина впала знову в проміжку. Вона не тримається стабільно, і публікація провалюється з повідомленням, що машина падала знову і знову з моменту публікації і все ще перезапускається.
Це працює незалежно від того, наскільки короткий список подій. Ковзне вікно з п'яти подій може приховати, скільки було збоїв, але не може приховати, що щойно відбувся новий; найновіша подія завжди зберігається.
З цією зміною локальне відтворення поводиться правильно: публікація провалюється, а попередній образ відновлюється. Є також тест, який імітує поведінку платформи — кожен погляд додає збій і запуск і обрізає список до п'яти — і перевіряє, що вердикт є провалом, а не успіхом.
Що ми з цього винесли
- Знайте форму даних, які ви рахуєте. Підрахунок за обмеженим списком перестає щось означати, коли список заповнений. Обмеження не було прихованим; ми просто не спроєктували перевірку з його урахуванням.
- Віддавайте перевагу питанню «чи сталося щось нове?» перед питанням «скільки всього сталося?». Найновіша мітка часу переживає обрізання. Загальна кількість — ні.
- Пізній провал гірший за ранній. Той самий зламаний білд безпечний, якщо публікація провалюється і відкочується, а коли його спершу оголошують успішним, він кладе сайт.
- Відтворюйте з реальними умовами. Для цього бага потрібна машина, яка вже впала достатньо разів, щоб заповнити список подій. Один швидкий збій у тесті цього б не показав.
Це виправлення доповнює інше, зроблене того ж дня, яке забезпечило, що відкат повертає стару версію, а не видаляє її: невдала повторна публікація ніколи не видаляє робочий бекенд. Якщо ваш власний застосунок не публікується, бо падає під час запуску, корисними будуть документація усунення несправностей публікації і наш посібник як налагоджувати застосунок, створений ШІ.