diff --git a/app/config.py b/app/config.py index 788a2c0..33ef516 100644 --- a/app/config.py +++ b/app/config.py @@ -75,8 +75,9 @@ normalize = true recover_gaps = true # Максимальный размер загружаемого файла, МБ max_upload_mb = 500 -# Сколько часов хранить результаты завершённых задач -keep_results_hours = 72 +# Сколько часов хранить результаты завершённых задач. Старые удаляются, +# файл базы после этого сжимается. 336 часов - две недели. +keep_results_hours = 336 [webhook] # Куда сообщать о готовых задачах. Пусто = не сообщать, забирайте опросом. @@ -118,7 +119,7 @@ class Settings: diarize: bool = False recover_gaps: bool = True max_upload_mb: int = 500 - keep_results_hours: float = 72.0 + keep_results_hours: float = 336.0 webhook_url: str = "" webhook_secret: str = "" update_enabled: bool = False @@ -206,7 +207,7 @@ def load_settings(config_path: Path | None = None) -> Settings: diarize=bool(proc.get("diarize", False)), recover_gaps=bool(proc.get("recover_gaps", True)), max_upload_mb=int(proc.get("max_upload_mb", 500)), - keep_results_hours=float(proc.get("keep_results_hours", 72)), + keep_results_hours=float(proc.get("keep_results_hours", 336)), webhook_url=str(hook.get("url", "")), webhook_secret=str(hook.get("secret", "")), https_domains=str(https.get("domains", "")), diff --git a/app/store.py b/app/store.py index 74bfbad..cb99066 100644 --- a/app/store.py +++ b/app/store.py @@ -116,7 +116,10 @@ class JobStore: self._update(job_id, status=JobStatus.RUNNING, started_at=time.time()) def mark_done(self, job_id: str, result: dict) -> None: + # Длительность становится известна только после декодирования, а в + # списке задач нужна без разбора всего результата - записываем сюда. self._update(job_id, status=JobStatus.DONE, finished_at=time.time(), + duration_sec=float(result.get("duration_sec") or 0.0), result=json.dumps(result, ensure_ascii=False)) def mark_failed(self, job_id: str, error: str) -> None: @@ -144,7 +147,20 @@ class JobStore: (JobStatus.DONE, JobStatus.FAILED, cutoff), ) self._conn.commit() - return cur.rowcount + removed = cur.rowcount + if removed: + self.vacuum() + return removed + + def vacuum(self) -> None: + """Возвращает системе место, освобождённое удалением. + + SQLite помечает страницы свободными, но файл не уменьшает: после + чистки многомесячной истории он остаётся прежнего размера. + """ + with self._lock: + self._conn.execute("VACUUM") + self._conn.commit() def recent(self, limit: int = 200) -> list[dict]: """Последние задачи без результатов: для списка нужны только заголовки. diff --git a/app/view.py b/app/view.py index fcddbdf..4420883 100644 --- a/app/view.py +++ b/app/view.py @@ -174,11 +174,15 @@ def render_job(job: dict) -> str: .roles .line {{ display:grid; grid-template-columns:76px 1fr; gap:10px; padding:4px 0; border-bottom:1px solid var(--line); }} .who2 {{ font-weight:600; font-size:13px; }} + button.copy {{ font:13px inherit; color:var(--fg); background:transparent; + border:1px solid var(--line); border-radius:4px; padding:3px 10px; + margin-left:10px; cursor:pointer; font-weight:400; }} + button.copy:hover {{ border-color:var(--dim); }}