# Реализовано: TTL-фикс + прерывание с сохранением + ETA + UI-таблица (v0.0.63) _2026-08-24. По плану `2026-08-24-implementation-plan-for-flash.md`. Код написан (роль Flash)._ ## Что сделано ### session.py — TTL-фикс + отмена - `touch(sid)`, `pause_ttl(sid)`, `resume_ttl(sid)` — продление/пауза/возобновление TTL. - В сессии `"cancel": threading.Event()`; `request_cancel(sid)`, `get_cancel_event(sid)`. ### scanner.py — прогресс и мягкая остановка LLM - `class CancelRequested`. - `scan_llm_ner(..., cancel_event, file_progress)`: отмена ТОЛЬКО между файлами (текущий добирается); события `file_start{chars,chunks}`, `file_chunk{chunks_done,chunks_total}`, `file_done{elapsed}`. ### obfuscator.py — частичный результат - `obfuscate()` возвращает `(zip, csv, meta)`: `meta=None` (штатно) или `{"cancelled": True, "processed", "total"}` (прерывание). - Трекинг `llm_done` (файлы с завершённым LLM). При отмене в LLM — в результат идут ТОЛЬКО файлы из `llm_done` (их обфускация корректна); при отмене в фазе замены — стоп после текущего файла. Отмена в replace НЕ проверяется, если LLM уже прерван (файлы из llm_done добираются). - Событие `extract_done{total_chars, per_file}` (объём текста для ETA). ### api_bp.py — API - `POST /api/cancel/`. - `process_stream`: `pause_ttl` в начале / `resume_ttl` в `finally`; передача `cancel_event` и `file_progress` в воркер; события `extract_done/file_start/file_chunk/file_done/cancelled`; heartbeat `llm` расширен: `eta_sec, done_chars, total_chars`; per-file ETA в `file_chunk`. - При закрытии вкладки (`disconnect`) ставится и `cancel`, и `cancel_event` (воркер останавливается). - legacy `process()` — фикс 3-значного возврата + TTL. ### index.html — UI - Кнопка «⏹ Прервать» + модал-подтверждение (объясняет, что сохранится). - Таблица 3 секций: «✓ Обработанные» (факт время) / «▶ Текущий файл» (прошло / ~осталось) / «○ Ожидают» (~оценка из скорости текущего файла). - Live-блок: «осталось ~X» (глобальная ETA), текущий файл с per-file ETA. - SSE-обработчики: extract_done/file_start/file_chunk/file_done/cancelled; done различает пропущенные (до extract_done) и готовые (после). ## Проверка - `py_compile` всех .py — OK; `node --check` (JS из index.html) — OK; `get_errors` — нет. - Локальные тесты логики отмены (FakeLLM): штатно=4 файла; отмена в LLM=3 сохранено; отмена до LLM=0..1 (текущий добирается); отмена после завершения=полный. - Смоук-тест: приложение создаётся, все роуты включая `/api/cancel/` зарегистрированы. ## ВАЖНО - Версия 0.0.63. **Код не задеплоен** — нужен редеплой на кластере и прогон реальных тестов (долгий прогон + прерывание).