fast log clear + robust API error handling
- fix: "Log leeren" without account filter used a plain DELETE over millions of rows. That held the sqlite write lock long enough that the scheduler's own log writes started failing with "database is locked", and the request itself eventually 500'd back as HTML "Internal Server Error" — which the frontend then tried to JSON.parse, producing the popup the user reported. Now uses DROP+CREATE for full clears (near-instant) and wal_checkpoint to reclaim space; per-account clear still uses a normal DELETE. - Raise sqlite busy_timeout from 10s to 60s so a legitimately slow writer no longer starves smaller ones. - retry-failed: single bulk DELETE with mail_uid IN (...) per account instead of one query per uid. - Both endpoints now return proper HTTPException(500, ...) with detail instead of letting the exception bubble as plain text. - Frontend: parseResponse() reads text first, then tries JSON. Both clearLogs() and retryFailed() surface the actual server message instead of crashing on non-JSON responses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+28
-5
@@ -228,13 +228,30 @@ function renderPaging(total, offset) {
|
||||
paging.innerHTML = html;
|
||||
}
|
||||
|
||||
async function parseResponse(resp) {
|
||||
// Liest die Response robust: JSON wenn möglich, sonst als Text.
|
||||
const text = await resp.text();
|
||||
try { return {ok: resp.ok, status: resp.status, data: JSON.parse(text)}; }
|
||||
catch { return {ok: resp.ok, status: resp.status, data: null, text}; }
|
||||
}
|
||||
|
||||
async function clearLogs() {
|
||||
if (!confirm('Log wirklich leeren?')) return;
|
||||
const accountId = document.getElementById('log-account').value;
|
||||
let url = '/api/logs/';
|
||||
if (accountId) url += `?account_id=${accountId}`;
|
||||
await fetch(url, {method: 'DELETE'});
|
||||
loadLogs();
|
||||
try {
|
||||
const resp = await fetch(url, {method: 'DELETE'});
|
||||
const r = await parseResponse(resp);
|
||||
if (!r.ok) {
|
||||
const msg = r.data?.detail || r.text || `HTTP ${r.status}`;
|
||||
alert('Fehler beim Leeren: ' + msg);
|
||||
return;
|
||||
}
|
||||
loadLogs();
|
||||
} catch(e) {
|
||||
alert('Netzwerk-Fehler: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function retryFailed() {
|
||||
@@ -244,10 +261,16 @@ async function retryFailed() {
|
||||
if (accountId) url += `?account_id=${accountId}`;
|
||||
try {
|
||||
const resp = await fetch(url, {method: 'POST'});
|
||||
const data = await resp.json();
|
||||
alert(`${data.unique_uids || 0} UID(s) neu vorgemerkt (${data.reset || 0} ProcessedMail-Einträge gelöscht). Werden beim nächsten Poll neu versucht.`);
|
||||
const r = await parseResponse(resp);
|
||||
if (!r.ok) {
|
||||
const msg = r.data?.detail || r.text || `HTTP ${r.status}`;
|
||||
alert('Fehler bei retry-failed: ' + msg);
|
||||
return;
|
||||
}
|
||||
const d = r.data || {};
|
||||
alert(`${d.unique_uids || 0} UID(s) neu vorgemerkt (${d.reset || 0} ProcessedMail-Einträge gelöscht). Werden beim nächsten Poll neu versucht.`);
|
||||
} catch(e) {
|
||||
alert('Fehler: ' + e.message);
|
||||
alert('Netzwerk-Fehler: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user