16 KiB
title, created, updated, type, namespace, status, tags, related
| title | created | updated | type | namespace | status | tags | related | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| План — переполнение диска Kraken (watchlist pipeline) | 2026-09-21 | 2026-09-21 | plan | family | in-progress |
|
|
План: переполнение диска Kraken — причины и ремонт
Инцидент 2026-09-21. Диск
/dev/sda1на Кра́кене (1.8 ТБ) заполнен до нуля байт. Radarr лежит сdisk I/O error.watchlist-nightlyиwatchlist-discoverостановлены. Причина:sync-down --batch 5качал 5 фильмов ежедневно без проверки свободного места.
Три независимых дефекта (все найдены 2026-09-21 по коду):
- Нет проверки места → диск забит под ноль (
sync_down.py)mark_queuedмолча проваливается → 3 метки⬇️потеряны (parser.py:77)- Правила «ужасы не качаются» НЕТ в коде вообще →
🧟♀️только рисуется, фильтр отсутствует;⭐приоритетнее🧟тоже не реализовано
Статус: Фаза 0 ожидает апрува Alex
| Фаза | Что | Статус |
|---|---|---|
| 0 | Освободить место (удалить 5 remux = 403.4 ГБ) | 🔴 ЖДЁТ АПРУВА |
| 0b | Снять ⬇️ у Шиндлера (396) + Неистового (107) |
⏸ после Фазы 0 |
| 1 | Фикс mark_queued — эмодзи-префиксы + возврат bool + лог провала |
⏸ НОВОЕ |
| 2 | MIN_FREE_GB в скрипт (стоп-кран) |
⏸ |
| 2b | Лимит размера файла | ❌ НЕ ДЕЛАЕМ — Alex: «лимит качества и так настроен» |
| 3 | Фильтр ужасов + приоритет ⭐ > 🧟 (правило новое, в коде его нет) |
⏸ НОВОЕ |
| 3b | Починить cleanup (видит только Radarr) |
⏸ отдельно |
| 4 | Восстановить 3 потерянные ⬇️ (Babylon, Midsommar, Triangle) |
⏸ после Фазы 1 |
| 5 | Вернуть крон с --batch 2 |
⏸ после Фаз 1–2 |
Сделано 2026-09-21: крон watchlist-nightly + watchlist-discover остановлен.
Бэкап crontab: ~/crontab-backup-20260921.txt.
Фаза 0 — Освободить место (БЛОКЕР)
Что удалять: 5 remux-файлов, 403.4 ГБ
Замер find -printf по /media/movies-radarr — 27 видеофайлов, remux'ов ровно 5:
92.0 GB /media/movies-radarr/Babylon (2022)/Babylon (2022) - UHD BD-Remux by Wild_Cat.mkv
89.4 GB /media/movies-radarr/Schindler's List (1993)/Schindler's.List.1993.2160p.HDR.BDRemux.mkv
85.6 GB /media/movies-radarr/Midsommar (2019)/Midsommar.2019.DC.BDREMUX.2160p.HDR.seleZen.mkv
79.7 GB /media/movies-radarr/Triangle of Sadness (2022)/Triangle.of.Sadness.2022.BDREMUX.2160p.HDR.seleZen.mkv
56.7 GB /media/movies-radarr/Unhinged (2020)/Неистовый.2020.UHD.Blu-Ray.Remux.2160p.mkv
Полный префикс пути: /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f.
⚠️ Что НЕ трогать
22 остальных файла — не remux (WEB-DL / BDRip / x264 / x265, 4–29 ГБ). Размер не признак:
| Файл | Размер | Тип |
|---|---|---|
Oldboy (2003)/Oldeuboi [2003].mkv |
28.6 GB | не remux |
Project.Hail.Mary...2160p.iT.WEB-DL.DV.HDR.H.265.mkv |
28.1 GB | не remux (WEB-DL) |
Whiplash (2014)/Одержимость (Whiplash) 2014.mkv |
23.7 GB | не remux |
Признак remux — имя файла: Remux / BDREMUX / BDRemux / BD-Remux.
🔴 Метки ⬇️ — факт: у 3 из 5 метки ПОТЕРЯНЫ (баг mark_queued)
family/documents/movies-watchlist.md — все 5 фильмов есть в списке (проверено grep по ru+en):
| Фильм | Строка | Метка ⬇️ |
|---|---|---|
| Неистовый (Unhinged) | 107: - [x] ⬇️ Неистовый |
✅ есть |
| Список Шиндлера | 396: - [ ] ⬇️ Список Шиндлера |
✅ есть |
| Babylon (2022) | 83: - [ ] Babylon (2022) |
❌ потеряна |
| Midsommar | 81: - [ ] 🧟♀️ midsommar 2019 |
❌ потеряна |
| Triangle of Sadness | 82: - [ ] Triangle of Sadness 2022 |
❌ потеряна |
⚠️ Питфолл поиска: Шиндлер записан по-русски («Список Шиндлера»). grep -i schindler его не находит → ошибочный вывод «фильма нет в списке». Искать и ru, и en.
Корень потери меток — баг mark_queued (parser.py:77):
pattern = re.compile(r'(^\s*-\s*\[ \]\s*)(' + re.escape(title) + r')', re.MULTILINE)
new_text = pattern.sub(r'\1⬇️ \2', text, count=1)
if new_text != text:
path.write_text(new_text) # ← молча ничего, если не совпало
- Между
]и названием бывает эмодзи-маркер (🧟♀️,✭) → regex не матчит. Строка- [ ] 🧟♀️ midsommar 2019не подпадает. titleможет не совпадать буквально (год/скобки) → не матчит.- Тихий провал: нет ошибки, нет лога.
sync_down.pyвызываетmark_queued(строки 98, 104, 113, 122) и не проверяет результат → считает, что всё ок.
Решение Alex: снять ⬇️ там, где есть (Шиндлер, Неистовый). [x] у Неистового не трогать — это отметка просмотра.
Почему удаляем файлами, а не через Radarr API
Radarr не отвечает — диск в нуле, SQLite не может писать:
{"message": "disk I/O error",
"description": "...System.Data.SQLite.SQLiteException (0x87AF045D): disk I/O error..."}
После освобождения места Radarr сам пересканирует и увидит hasFile=false.
Фаза 1 — Фикс mark_queued (корень потери меток) 🆕
Файл: watchlist_sync/parser.py:77
Дефект: regex ожидает название сразу после - [ ], но в файле бывает эмодзи-маркер. Плюс тихий провал:
pattern = re.compile(r'(^\s*-\s*\[ \]\s*)(' + re.escape(title) + r')', re.MULTILINE)
new_text = pattern.sub(r'\1⬇️ \2', text, count=1)
if new_text != text:
path.write_text(new_text) # ← молча ничего, если не совпало
Что чинить:
# 1. Разрешить опциональные маркеры перед названием (в т.ч. ⭐ — он может стоять где угодно)
pattern = re.compile(
r'(^\s*-\s*\[ \]\s*)'
r'([🧟♀️✭🗓️❓⭐]\s*)?'
r'(' + escaped + r')',
re.MULTILINE
)
# 2. Возвращать bool — вставилась ли метка
# 3. При провале — log warning / raise, а не тишина
Плюс: в sync_down.py (строки 98, 104, 113, 122 — четыре места) проверять результат:
if not mark_queued(watchlist, item.title):
print(f" [!] failed to mark ⬇️ for {item.title!r}")
Проверка: прогнать на копии файла → убедиться, что 3 проблемные строки (81, 82, 83) получают метку.
⚠️ Наличие ⭐ в коде уже известно (parser.py:_clean): «U+2B50 may sit ANYWHERE in the title ("Простите за беспокойство ⭐ 2018")» → проверять всю строку, не только конец.
Фаза 3 — Фильтр ужасов + приоритет ⭐ > 🧟 (ПРАВИЛО НОВОЕ) 🆕
🔴 Установлено фактами: правила «ужасы не качаются» в коде НЕТ вообще.
| Компонент | Есть? | Где |
|---|---|---|
is_horror() — определяет жанр |
✅ | resolver.py:43 (по жанрам TMDB, 27 = Horror) |
mark_horror() — ставит 🧟♀️ |
✅ | parser.py:156, вызов cli.py:127 |
Фильтр в sync_down |
❌ ОТСУТСТВУЕТ | sync_down.py не вызывает is_horror() — проверено по всему файлу |
🧟♀️ — только визуальная метка. Единственный фильтр в sync_down — MIN_RATING (строка 63).
Поэтому Midsommar скачался, будучи помеченным 🧟♀️.
Правило, которое надо реализовать (сформулировано Alex 2026-09-21):
| Случай | Действие |
|---|---|
Ужас + ⭐ |
качаем — ⭐ приоритетнее 🧟 |
Ужас без ⭐ |
пропускаем |
| Не ужас | качаем как обычно |
def should_skip_horror(candidate, raw_line: str) -> bool:
if not candidate.is_horror():
return False
if '\u2b50' in raw_line: # ⭐ — явный приоритет пользователя
return False
return True # ужасы без ⭐ — пропускаем
Что нужно:
parser.py— читать наличие⭐в любой позиции строки → новое полеpriority: boolвWatchItemsync_down.py— перед добавлением в Radarr:if should_skip_horror(c, item.raw): continuecli.py— при маркировке: ужас +⭐→🧟♀️не навешивать
Фаза 4 — Восстановить потерянные ⬇️
Три фильма без метки (после фикса mark_queued — правильным инструментом, не руками):
- строка 83:
Babylon (2022) - строка 81:
🧟♀️ midsommar 2019 - строка 82:
Triangle of Sadness 2022
Проверка: grep по каждой строке → метка на месте.
Фаза 5 — Вернуть крон
После того как Фазы 1–2 проверены и стоп-кран работает:
- вернуть строки
watchlist-nightly(01:00) иwatchlist-discover(вс 09:00) в crontab; - снизить
--batchс 5 до 2.
Фаза 3b — Починить cleanup (отдельно, осторожно)
Дефект: cleanup сопоставляет [x] из watchlist с Radarr-библиотекой, а просмотренное лежит в /media/movies (ручные торренты). Пересечение = 0 → удаляет 0 файлов.
Замер 2026-09-21: watchlist [x] items: 177 / radarr movies with file: 28 / nothing to delete.
Это не причина инцидента — cleanup не мог занять место, он только удаляет. Расширять его — отдельная задача, идёт после Фаз 0–2.
Порог MIN_FREE_GB — ⏸ ожидает решения Alex
Предложение: 100 ГБ. Alex ещё не подтвердил число.
Уроки
- Любой скрипт, ставящий закачки в очередь, ОБЯЗАН проверять свободное место до добавления. Лимита качества недостаточно — он про тип релиза, не про размер.
- «Radarr молчит / I/O error» на заполненном диске — сначала проверить место, потом конфиг и сеть.
- Крон в 01:00 без присмотра = диск заполняется незаметно. Тревога при >порога не настроена: cleanup писал «nothing to delete» и молчал.
- Не выдавать догадки за факт. Первая версия разбора указывала на
cleanupкак виновника — Alex поправил: cleanup удаляет, а не занимает. Виновник —sync-down. - Функция, которая «тихо ничего не делает» при провале — источник невидимых дефектов.
mark_queuedмолчал → 3 метки потеряны, никто не заметил. Возвращатьboolи логировать. - Метка ≠ правило.
🧟♀️рисовалась, но фильтра не было — Midsommar скачался. Если метка должна что-то запрещать — запрет надо писать отдельно. - Искать и по-русски, и по-латинице.
grep -i schindlerне нашёл «Список Шиндлера» → ложный вывод «фильма нет». Проверять оба написания перед любым утверждением.
Фаза 2 — Стоп-кран MIN_FREE_GB (главный фикс заполнения)
Цель: перед добавлением фильма в Radarr проверить свободное место. Если мало — не добавлять.
Где: watchlist_sync/sync_down.py (или cli.py — уточнить по коду перед правкой).
# Minimum free space on the media disk before queueing new downloads.
# Prevents filling the disk to zero (incident 2026-09-21).
MIN_FREE_GB = 100 # ← значение согласовать с Alex
Проверка перед циклом добавления:
st = os.statvfs(MEDIA_PATH) # НЕ shutil.disk_usage("/media")!
free_gb = (st.f_bfree * st.f_frsize) / (1024**3)
if free_gb < MIN_FREE_GB:
print(f"only {free_gb:.1f} GB free (< {MIN_FREE_GB} GB) — not queueing anything")
return
⚠️ Питфолл: /media — не медиа-диск, это пустая папка на SD-карте (/dev/mmcblk0p2, 14 ГБ). Реальный диск — /srv/dev-disk-by-uuid-6194539b-.../. Брать os.statvfs по реальному корню.
⚠️ df завышает (~+4%, root-резерв ext4). Для порогов использовать os.statvfs.
Порядок работ: бэкап → правка → dry-run → проверка Alex → коммит.
Фаза 2 — Лимит размера ❌ НЕ ДЕЛАЕМ
Alex 2026-09-21: «лимит качества и так настроен». Профиль WEB-4K (no remux) (Radarr/Sonarr id 7) уже запрещает Remux-1080p/2160p и BR-DISK. Новых лимитов не вводим.
⚠️ Но: профиль не ограничивает размер — только тип релиза. Все 5 виновников качались под профилем Any (id 1) до фикса 2026-09-04. Существующие файлы под новый профиль не подпадают.
Связанные заметки
- family/projects/watchlist-automation — полный pipeline, статус крона
- family/plans/watchlist-cleanup — механизм cleanup (порог 90%, лимит 10)
- family/how-to/arr-stack-kraken — *arr стек, профили качества, API