
Отримали ми нещодавно від користувачів баг – один з мікросервісів, що має моніторити директорію на FTP і вичитувати з неї файли, щоб передати дані з них в інші сервіси, почав з незрозумілих причин падати. І най би собі просто падав і перезапускався, але він ще й блокував файли, що не встиг обробити до кінця.
Почали шукати причину і розбиратись. По коду – наче все правильно. Поки файл не вичитано до кінця, метадата про нього зберігається в окремій message queue, і навіть після перезапуску, сервіс має продовжити працювати з файлом там, де його зупинили.
Тестили ми це наступним чином: закидували багато великих файлів на FTP, і коли сервіс починав їх парсити – “вбивали” сервіс, раптово і жорстоко 😈
Але виявилось, що тест треба було проводити по іншому – під час обробки вбивати не той сервіс, що обробляє файли, а той, що отримує вже оброблені дані через REST.
Чому так? Стався невдалий збіг одразу кількох факторів:
✅ як би жорстоко не видаляти мікросервіс, він все одно встигає фіналізувати критичні операції, і потрібної помилки не стається
✅ фреймворк, на якому написано мікросервіс, виявився занадто розумним. Не зважаючи на явну обробку помилок в коді, він неявно, в нетрях конфігурацій, має “допомагати” розробникам. Тому при помилці блокував файли і видаляв інформацію про них з queue. Дякую, блін!
З аналізу цього багу я зробив для себе 2 висновки:
1️⃣ при тестуванні E2E сценаріїв, так чи інакше треба ламати по черзі кожен сервіс в ланцюжку викликів, щоб переконатись, що помилки обробляються коректно
2️⃣ навіть якщо розробник показує код і каже, що явно обробив всі помилки, треба пам’ятати, що ПЗ набагато складніше і кожен контекст вимагає додаткового аналізу.
вся, але він ще й блокував файли, що не встиг обробити до кінця.