add "reset all processed" button + endpoint
POST /api/filters/reset-all-processed drops and recreates the processed_mails table — sekundenschnell auch bei Millionen Zeilen via DROP+CREATE (same pattern as the fast clear-logs). Safe because already-moved mails are no longer in the source folder, so a fresh re-evaluation cannot re-move them, only pick up ones that were skipped due to a rule bug (e.g. the has_attachment fix). Button "Alle Regeln zurücksetzen" next to "Neue Regel" on the filter list, with a confirmation dialog and result feedback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-2
@@ -1,10 +1,10 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy import func, text
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import logging
|
||||
|
||||
from app.database import get_db
|
||||
from app.database import engine, get_db
|
||||
from app.models.db_models import (
|
||||
Account,
|
||||
FilterAction,
|
||||
@@ -33,6 +33,27 @@ def _reset_processed_for_rule(db: Session, rule_id: int) -> int:
|
||||
router = APIRouter(prefix="/api/filters", tags=["filters"])
|
||||
|
||||
|
||||
@router.post("/reset-all-processed")
|
||||
def reset_all_processed(db: Session = Depends(get_db)):
|
||||
"""Setzt den 'verarbeitet'-Status ALLER Mails zurück — alle Regeln bewerten
|
||||
beim nächsten Poll wieder jede Mail im Ordner neu. Sicher, weil schon
|
||||
verschobene Mails nicht mehr in der Quelle liegen und daher nicht erneut
|
||||
verschoben werden können. Nutzt DROP+CREATE statt DELETE, damit auch
|
||||
bei Millionen Zeilen sekundenschnell."""
|
||||
try:
|
||||
row_count = db.query(ProcessedMail).count()
|
||||
db.close() # Sitzung freigeben, damit DDL nicht am Lock hängt
|
||||
with engine.begin() as conn:
|
||||
ProcessedMail.__table__.drop(conn, checkfirst=True)
|
||||
ProcessedMail.__table__.create(conn, checkfirst=True)
|
||||
conn.execute(text("PRAGMA wal_checkpoint(TRUNCATE)"))
|
||||
logger.info("ProcessedMail vollständig zurückgesetzt (%d Einträge entfernt)", row_count)
|
||||
return {"reset": row_count}
|
||||
except Exception as e:
|
||||
logger.exception("reset-all-processed fehlgeschlagen")
|
||||
raise HTTPException(500, f"Fehler beim Zurücksetzen: {e}")
|
||||
|
||||
|
||||
@router.post("/retry-failed")
|
||||
def retry_failed_fetches(account_id: int | None = None, db: Session = Depends(get_db)):
|
||||
"""Löscht ProcessedMail-Einträge für UIDs, für die es einen ERROR-Log
|
||||
|
||||
@@ -224,6 +224,8 @@ function renderFilters() {
|
||||
let html = `
|
||||
<div style="display:flex; gap:0.75rem; align-items:center; margin-bottom:1rem; flex-wrap:wrap;">
|
||||
<button onclick="openNewFilter()" style="margin-bottom:0;">Neue Regel</button>
|
||||
<button class="outline" onclick="resetAllProcessed()" title="Verwirft den 'verarbeitet'-Marker aller Mails. Beim nächsten Poll werden alle Ordner-Mails neu gegen alle Regeln geprüft. Sicher — schon verschobene Mails sind nicht mehr in der Quelle."
|
||||
style="margin-bottom:0;">Alle Regeln zurücksetzen</button>
|
||||
<input type="search" id="filter-search" placeholder="Filter durchsuchen..."
|
||||
value="${searchTerm.replace(/"/g, '"')}"
|
||||
oninput="renderFilters()"
|
||||
@@ -530,6 +532,23 @@ async function deleteFilter(id) {
|
||||
loadFilters();
|
||||
}
|
||||
|
||||
async function resetAllProcessed() {
|
||||
if (!confirm('Alle Mails werden beim nächsten Poll erneut von allen Regeln geprüft. Fortfahren?')) return;
|
||||
try {
|
||||
const resp = await fetch('/api/filters/reset-all-processed', {method: 'POST'});
|
||||
const text = await resp.text();
|
||||
let data = null;
|
||||
try { data = JSON.parse(text); } catch {}
|
||||
if (!resp.ok) {
|
||||
alert('Fehler: ' + (data?.detail || text || `HTTP ${resp.status}`));
|
||||
return;
|
||||
}
|
||||
alert(`${data?.reset ?? 0} Einträge zurückgesetzt. Beim nächsten Poll (max ~1-2 min) wird alles neu geprüft.`);
|
||||
} catch(e) {
|
||||
alert('Netzwerk-Fehler: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Ordner-Browser (Baumansicht) ---
|
||||
|
||||
let folderTargetInputName = null;
|
||||
|
||||
Reference in New Issue
Block a user