The existing daily cleanup never effectively ran: it was an interval job counted from container start (reset on every deploy), it called asyncio.get_event_loop() from a worker thread, and even when deleting, SQLite never returns freed pages to the filesystem. Live DB: 4.1 GB, of which 2.6 GB log and 0.6 GB unused pages. New maintenance service, scheduled daily at MAINTENANCE_HOUR_UTC:30 and once 5 minutes after every start: - delete log entries older than LOG_RETENTION_DAYS (30) and keep at most LOG_MAX_ENTRIES (200k) newest ones - delete processed_mails markers of deleted rules/accounts (FKs are not enforced by SQLite) - VACUUM when >25% of the file is unused, only if free disk space covers the copy; never runs twice in parallel GET/POST /api/logs/maintenance expose status and a manual run; the log menu shows DB size, entry count and last run, with "Datenbank aufräumen & verkleinern". Removed the dead cleanup_old_logs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
26 lines
889 B
Python
26 lines
889 B
Python
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
database_url: str = "sqlite:///data/mailfilter.db"
|
|
yaml_config_path: str = "config/filters.yaml"
|
|
encryption_key: str = ""
|
|
yaml_sync_on_startup: bool = True
|
|
log_level: str = "INFO"
|
|
# Ausführliches Verarbeitungslog (jede Nicht-Übereinstimmung, jede Regel pro
|
|
# Poll). Erzeugt Millionen Einträge — nur zur Fehlersuche einschalten.
|
|
log_verbose: bool = False
|
|
# Log-Rotation: Einträge älter als N Tage löschen und höchstens so viele
|
|
# behalten (die neuesten). Läuft täglich zur angegebenen Stunde (UTC) und
|
|
# einige Minuten nach jedem Start.
|
|
log_retention_days: int = 30
|
|
log_max_entries: int = 200_000
|
|
maintenance_hour_utc: int = 2
|
|
|
|
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
|
|
|
|
|
|
settings = Settings()
|