Расскажи о своём самом крупном факапе
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Крупный факап и уроки из него
История
Один из самых больших факапов произошёл на третьем году работы в проекте по внедрению ЗУП+. Мы заканчивали миграцию с предыдущей системы учёта на новую систему на 1С, и нужно было загрузить исторические данные по зарплате за два года.
Что произошло
И разработал регистр сведений для хранения исторических расчётов и написал скрипт загрузки данных из старой системы. Проверил на тестовой базе — работало. Но когда закатили на production:
// Примерно такой код был
Процедура ЗагрузитьРасчёты()
Для Каждого Строка Из ТаблицаРасчётов Цикл
Регистратор = Документы.РасчётнаяВедомость.СоздатьДокумент();
Регистратор.Дата = Строка.ДатаРасчёта;
// Много полей...
Регистратор.Записать();
// Запись в регистр
Движение = РегистрСведений.РасчётныеДанные.ОстановкаНиже();
Движение.Период = Дата;
// ...
КонецЦикла;
КонецПроцедуры;
Проблема: я не обвернул весь процесс в транзакцию, не сделал отката при ошибке, и главное — загрузил данные дважды, потому что скрипт повис и я переустал его. Результат:
- В базе дублировались записи по зарплате
- Бухгалтер сразу заметил что суммы считаются неправильно (в 2 раза больше)
- Все регистры расчётов испорчены
- Нужно откатывать всю базу на backup
Последствия
- Потеря времени: откатываемся на day-old backup (потеря данных за день работы)
- Потеря доверия: бухгалтер ещё месяц боялась что базу сломаем заново
- Стресс: нужно было переделать в выходные (это был вторник вечер)
- Репутация: я получил репутацию разработчика который делает косяки
Причины факапа
- Недостаточное тестирование на большом объёме: на тестовой базе было 10 сотрудников, на проде 500+
- Неправильная обработка ошибок: не предусмотрел механизм отката
- Отсутствие идемпотентности: скрипт не мог быть запущен дважды
- Перелив кэша: может быть из-за размера данных произошли таймауты
- Отсутствие логирования: не знал на каком шаге скрипт завис
- Отсутствие одобрения: не просил ревью у опытного разработчика
Что я сделал
После факапа я полностью переписал скрипт:
Процедура ЗагрузитьРасчётыСОтката()
НачатьТранзакцию();
Попытка
// Очистка предыдущих данных если загружались
ОчиститьПредыдущиеДанные();
// Логирование начала
ЗаписатьВЖурналРегистрации(
"ЗагрузкаРасчётов",
УровеньЖурналаРегистрации.Информация,
, ,
СтрШаблон("Начало загрузки %1 записей", ТаблицаРасчётов.Количество())
);
Счётчик = 0;
Для Каждого Строка Из ТаблицаРасчётов Цикл
ОбработатьСтрокуРасчёта(Строка);
Счётчик = Счётчик + 1;
// Логирование прогресса
Если Счётчик % 100 = 0 Тогда
ЗаписатьВЖурналРегистрации(
"ЗагрузкаРасчётов",
УровеньЖурналаРегистрации.Информация,
, ,
СтрШаблон("Обработано %1 записей", Счётчик)
);
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписатьОшибку(
"Ошибка при загрузке расчётов",
ОписаниеОшибки()
);
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры;
Уроки
- Всегда обворачивай в транзакцию — критичные операции требуют atomicity
- Тестируй на реальных объёмах — 10 != 500 записей, поведение может отличаться кардинально
- Логирование + прогресс — должно быть понятно где упал скрипт
- Идемпотентность — скрипт должен быть безопасен при повторном запуске
- Code review перед миграциями — никогда не загружай критичные данные сам, согласуй с коллегой
- Резервные копии — всегда снимай backup перед масштабными операциями
- Dry run на копии — сначала на копии базы, потом на проде
Сейчас
Этот факап сделал меня лучше разработчиком. Теперь я:
- Всегда проверяю миграции на правильном объёме данных
- Пишу скрипты с обработкой ошибок и логированием
- Обязательно показываю загрузкам другим разработчикам перед production
- Документирую процесс загрузки, чтобы если что — можно было отката
Дело не столько в том что произошла ошибка, а в том как я на неё реагировал и что из этого выучил. Вот это ценит работодатель.