Docker Image CI / build (pull_request) Waiting to run
Ревью #44: allowlist снапшота был неполон -> спец-медиа блоки тихо выпадали на
cache-hit (нарушение golden-render инварианта). Исправлено:
- Снапшот+восстановление 11 типов (story, contact, location, venue, dice, game,
giveaway, giveaway_winners, checklist, paid_media + live_photo) — ровно те
подполя, что читает _format_special_media/find_file_id_in_message.
SNAPSHOT_VERSION 1->2 (v1-файлы без новых ключей инвалидируются).
- Render-parity тест (tests/test_snapshot_render_parity.py): корпус из 35+ кейсов
(все медиа/спец-медиа/web_page/poll/forward Case 1-5/reactions/media group),
live-рендер == restore(snapshot(live))-рендер байт-в-байт через реальный
пайплайн; мутационно проверено (выброс поля -> тест краснеет).
- F1: file_size досниман для document/audio/animation/video_note/story-media
(правило '>100MB не кэшировать' в _save_media_file_ids читает file_size у любого
выбранного медиа-объекта; раньше был только у video/live_photo -> >100MB документ
ошибочно кэшировался на cache-hit).
- flake8/pylint-хедеры на 3 новых тест-файла.
post_parser.py/rss_generator.py не тронуты; pickle отсутствует.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Docker Image CI / build (pull_request) Waiting to run
Кеш истории (data/tgcache/) больше не хранит pickle живых объектов pyrogram.
Новый модуль message_snapshot.py: при записи из Message извлекается JSON-словарь
по явному allowlist (снапшот), при чтении восстанавливается duck-typed
CachedMessage (CachedStr с .html, mutable, deepcopy-safe), неотличимый для
пайплайна рендера от Message. post_parser.py и rss_generator.py НЕ изменены.
tg_cache.py переписан на generic JSON-store (pickle удалён полностью):
- _store_entry/_load_entry: атомарная запись через уникальный .tmp.<uuid4> +
os.replace, finally чистит свой tmp; версия/TTL/битый JSON -> None;
- пути <safe_key>.history.json / .chatinfo.json;
- пакет B: префиксный limit (miss только когда cached_limit<limit и есть ещё);
- пакет F: джиттер TTL при записи (random.uniform(0.8,1.0), на чтении random не
зовётся) + sweep_tgcache(age) + cleanup_legacy_cache_files;
- api_server.py: старт-cleanup+sweep в lifespan, per-pass sweep в cache_media_files,
удаление legacy data/media_file_ids.json.
closes#23
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>