From:To:
11¶ **Odoo-модуль `auto_database_backup`, сентябрь 2025 — сентябрь 2026.**
22
3− Модуль делает ровно то, что звучит: снимает копию базы по расписанию и кладёт её куда скажут — на диск, в Google Drive, в Dropbox, в S3. Ставится в один клик.
3+ Cybrosys — индийская компания, партнёр Odoo. В их открытом репозитории [CybroAddons](https://github.com/CybroOdoo/CybroAddons) лежат сотни модулей. Один из них снимает копию базы по расписанию и кладёт её куда скажут — на диск, в Google Drive, в Dropbox, в S3. Ставится в один клик, и стоит у людей на боевых серверах.
4+
5+ Это история про то, как один человек снаружи нашёл в нём две дыры, и что было дальше.
46¶ **19 сентября 2025 — модуль рождается.**
57
68 [`Sep 1 : [ADD] Initial Commit 'auto_database_backup'`](https://github.com/CybroOdoo/CybroAddons/commit/6f710d5)
79
810 Внутри — [поле](https://github.com/CybroOdoo/CybroAddons/blob/19.0/auto_database_backup/models/db_backup_configure.py), которое станет главным героем:
911
1012 ```python
1113 generated_exception = fields.Char(...)
1214 ```
1315
1416 Сюда пишется текст ошибки, если бэкап не удался. По этому полю потом смотрят, жив ли бэкап.
15−¶ **18 июня 2026 — приходит человек с числами.**
17+¶ **18 июня 2026 — приходит Джанфранко.**
1618
17− Проходит девять месяцев. [GianfrancoNQ](https://github.com/GianfrancoNQ) открывает [issue #421](https://github.com/CybroOdoo/CybroAddons/issues/421). Заголовок длиной в абзац и содержит диагноз целиком:
19+ Проходит девять месяцев. [Gianfranco Niquín](https://github.com/GianfrancoNQ), инженер из компании NIQERA, открывает [issue #421](https://github.com/CybroOdoo/CybroAddons/issues/421).
1820
19− > backups silently fail — generated_exception never reset + temp files leak until disk fills
21+ Он не пишет «у меня не работает». Он приносит разбор на две страницы, с двумя багами, замерами с боевого сервера и готовым PR. Заголовок задачи — уже диагноз:
2022
21− Это не жалоба. Это разбор на две страницы, с двумя багами, замерами и готовым PR.
22−¶ **Первый баг.** `generated_exception` пишется только внутри `except`. Нигде и никогда не очищается.
23+ > backups silently fail — generated_exception never reset + temp files leak until disk fills
24+ >
25+ > *бэкапы падают молча — `generated_exception` никогда не сбрасывается, плюс временные файлы текут, пока не забьют диск*
26+¶ **Первый баг**, его словами:
2327
2428 > once a backup fails, the configuration record stays flagged in error **forever**, even after many subsequent successful backups. Any monitoring based on that field is permanently wrong.
25−
26− Поле, заведённое, чтобы показывать здоровье, после первого же сбоя показывает болезнь вечно.
27−¶ **Второй баг.** Каждый прогон создаёт временный файл и временный каталог с полной копией файлового хранилища. Если процесс убивают, менеджеры контекста не отрабатывают, и мусор остаётся.
29+ >
30+ > *стоит бэкапу упасть один раз, и запись настройки остаётся помеченной ошибкой **навсегда** — даже после множества последующих удачных прогонов. Любое наблюдение, построенное на этом поле, врёт с этого момента и постоянно.*
31+¶ **Второй баг** — про мусор, остающийся после убитого процесса:
2832
2933 > Once the temp dir is full, **every** backup then fails with `[Errno 28] No space left on device`, which masks the original problem.
30−
31− Первый отказ порождает мусор. Мусор забивает диск. Полный диск валит все следующие прогоны — и в журнале теперь стоит не та причина, что сломала первый.
32−¶ И числа с боевого сервера:
34+ >
35+ > *когда временный каталог забит, **каждый** следующий бэкап падает с «нет места на устройстве» — и это маскирует исходную проблему.*
36+¶ И числа, ради которых стоит читать целиком:
3337
3438 > On a production instance (Amazon S3 destination) backups failed silently for ~17 days; ~90 GB of orphan temp files had accumulated in the container's `/tmp` while the host disk still had plenty of free space.
39+ >
40+ > *на боевом сервере (копии уходили в Amazon S3) бэкапы молча не снимались около 17 дней; в `/tmp` контейнера накопилось порядка 90 ГБ осиротевших временных файлов, при том что на диске хоста места было полно.*
3541
36− Семнадцать дней. Девяносто гигабайт. На хосте места при этом полно — забит был `/tmp` внутри контейнера, куда никто не смотрит.
42+ Семнадцать дней. Всё это время в интерфейсе не мигало ничего. Копий не было — и это выглядело точно так же, как если бы они были.
3743
38− Всё это время в интерфейсе не мигало ничего. Копий не было — и это выглядело точно так же, как если бы они были.
39−¶ **15 июля 2026 — ответ.**
44+ Подпись под отчётом: *Reported and fixed by NIQERA* — он не просто пожаловался, он принёс правку.
45+¶ **15 июля 2026 — отвечает Ризвана.**
4046
41− Через двадцать семь дней приезжает [`Jul 15: [FIX] Bug Fixed 'auto_database_backup'`](https://github.com/CybroOdoo/CybroAddons/commit/2ada471357ba15e4ea237f2ebfcd6ac203284d94).
47+ Через двадцать семь дней приезжает [`Jul 15: [FIX] Bug Fixed 'auto_database_backup'`](https://github.com/CybroOdoo/CybroAddons/commit/2ada471357ba15e4ea237f2ebfcd6ac203284d94) за авторством Risvana ([RisvanaCybrosys](https://github.com/RisvanaCybrosys)).
4248
43− Три файла, `+123/-123` в том самом `db_backup_configure.py`. Похоже на ответ.
49+ Три файла, `+123/-123` в том самом `db_backup_configure.py`. Очень похоже на ответ Джанфранко.
4450
4551 В release notes написано, что именно починили:
4652
4753 > Fixed the issue while generating Nextcloud backup
54+ >
55+ > *Исправлена проблема при создании копии в Nextcloud*
4856
4957 Nextcloud. Не то.
50−¶ **20 июля 2026 — починка приходит боком.**
58+¶ **20 июля 2026 — Аджмал, тридцать пять файлов.**
5159
52− Ещё через пять дней — [`Jul 20 [IMP] Structural Change, Code Refactoring, New Features`](https://github.com/CybroOdoo/CybroAddons/commit/909981a).
60+ Ещё через пять дней приходит [`Jul 20 [IMP] Structural Change, Code Refactoring, New Features`](https://github.com/CybroOdoo/CybroAddons/commit/909981a), автор Ajmal ([AjmalCybro](https://github.com/AjmalCybro)).
5361
5462 Тридцать пять файлов. И где-то внутри появляется строка:
5563
5664 ```python
5765 values['generated_exception'] = False
5866 ```
5967
60− Первый баг закрыт. В том же коммите заводится и тест. В issue об этом не сообщает никто.
68+ Первый баг Джанфранко закрыт. В том же коммите заводится и тест на него.
69+
70+ В задаче об этом не сообщает никто.
6171¶ **1 сентября 2026 — что осталось.**
6272
6373 [Issue #421](https://github.com/CybroOdoo/CybroAddons/issues/421) открыт. Спустя два с половиной месяца. Комментариев ноль.
6474
6575 По [текущему файлу](https://github.com/CybroOdoo/CybroAddons/blob/19.0/auto_database_backup/models/db_backup_configure.py) в ветке `19.0`:
6676
6777 ```
6878 grep -c "orphan\|cleanup\|sweep" → 0
6979 ```
7080
7181 Второй баг — тот, из-за которого натекли девяносто гигабайт, — живёт.
7282
7383 Починилась ровно та половина, из-за которой врал мониторинг. Не починилась та, из-за которой забивается диск.
84+¶ **Про людей, а не про халатность.**
85+
86+ Соблазн прочитать это как «в Cybrosys плохо работают» надо погасить сразу.
87+
88+ В репозитории сотни модулей. Ризвана и Аджмал закрывают поток задач по всему репозиторию — и за пять дней сделали и точечную правку, и рефакторинг на тридцать пять файлов. Отчёт от постороннего человека попадает в этот поток наравне со всем остальным.
89+
90+ Ошибка здесь не в людях, а в положении: **между тем, кто нашёл, и тем, кто чинит, нет разговора.** Джанфранко не знает, что его первый баг закрыт. Аджмал, вероятно, не знает, что закрыл именно его. А второй баг не закрыл никто, потому что оба считают вопрос как-то решённым.
7491## Что это значит для нас
75921. Убирать мусор в начале прогона, а не в конце
7693 Сметать брошенные временные файлы первым действием, до всего остального.
7794 why: Процесс, убитый сигналом, до своей уборки не доходит никогда — менеджеры контекста при SIGKILL не работают. Следующий прогон — единственный, кто может убрать за предыдущим.
7895 - [ ] Уборка стоит ДО снятия, а не после
7996 - [ ] Проверено запуском: состаренный временный файл действительно удаляется
8097 - [ ] Обычный отказ вдобавок убирает за собой сразу
8198 → Отчёт с замерами: 17 дней, 90 ГБ — https://github.com/CybroOdoo/CybroAddons/issues/421
82992. Сделать так, чтобы успех гасил прошлую ошибку
83100 Найти в своём коде поля состояния, которые только ставятся и нигде не снимаются.
84101 why: Состояние, которое умеет только портиться, — это не состояние, а счётчик обид. Любое наблюдение поверх него врёт после первого же сбоя и навсегда.
85102 - [ ] Найдено каждое место, где поле выставляется
86103 - [ ] Есть хотя бы одно место, где оно снимается при успехе
87104 - [ ] Проверено: отказ, затем успех — состояние стало чистым
88105 → Коммит, где сброс флага появился тихо — https://github.com/CybroOdoo/CybroAddons/commit/909981a
891063. Завести положительный сигнал, а не только тревогу
90107 При УСПЕХЕ стучаться наружу, а наблюдение настроить на ОТСУТСТВИЕ стука.
91108 why: Семнадцать дней тишины случились не потому, что тревога не сработала, а потому что послать её было некому. Молчание мёртвого сторожа неотличимо от молчания исправного.
92109 - [ ] Есть внешний монитор, который ждёт стук и ругается на его отсутствие
93110 - [ ] Период монитора больше периода бэкапа
94111 - [ ] Канал связи в образе ДЕЙСТВИТЕЛЬНО есть — проверено, а не предположено
951124. Проверять снятое, а не факт снятия
96113 Читать архив после создания (для Postgres — pg_restore --list) и требовать разумного числа объектов. Готовое имя — только проверенному файлу.
97114 why: Успешный дамп пустой базы — самый убедительный из фальшивых бэкапов. Код возврата ноль означает лишь, что инструмент не упал.
98115 - [ ] Архив читается после снятия, а не только проверяется код возврата
99116 - [ ] Есть порог, отсекающий пустой дамп
100117 - [ ] Хотя бы один раз копия РАЗВЁРНУТА в пустую базу и сверена с оригиналом
101118 → pgBackRest: отдельная команда verify — https://github.com/pgbackrest/pgbackrest/tree/main/src/command/verify
102119 → docker-postgres-backup-local: атомарное переименование, но без проверки — https://github.com/prodrigestivill/docker-postgres-backup-local/blob/master/backup.sh
103120¶ Есть в этой истории одна деталь, которую трудно не заметить.
104121
105122 Человек потратил вечер, нашёл два бага, замерил ущерб, написал отчёт на две страницы и приложил готовую правку. Одну его находку молча починили внутри рефакторинга из тридцати пяти файлов. Вторую не починили. Ему не ответили ни разу.
106123
107124 Модуль, о котором шла речь, ломался тем, что ничего никому не сообщал.