retry-failed: only pick open errors and mark them as retried
"Fehlgeschlagene neu einlesen" reported the same 29 mails on every click: it selected all error log entries ever written and never noted that one had already been retried. Error log entries now get retried_at when they are picked up; the endpoint only considers entries without it. If the mail fails again, the scheduler writes a new, open error entry, so a second click right after the first reports 0. The log shows retried errors greyed out with "↻ erneut versucht <Zeit>", and the result dialog says how many open error entries and mails were requeued. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -116,6 +116,9 @@
|
||||
.logs .l.lv-error { box-shadow:inset 3px 0 0 #dc3545; }
|
||||
.logs .l.lv-warning { box-shadow:inset 3px 0 0 #ffc107; }
|
||||
.logs .l.lv-success { box-shadow:inset 3px 0 0 #28a745; }
|
||||
.logs .l.retried { box-shadow:inset 3px 0 0 #c9ced6; }
|
||||
.logs .l.retried > span:not(.l-main), .logs .l.retried .l-mail { opacity:0.55; }
|
||||
.retried-tag { font-size:0.72rem; font-weight:600; padding:0 0.35rem; border-radius:3px; background:#eef0f3; color:#555; white-space:nowrap; }
|
||||
.l-time { color:var(--pico-muted-color); font-variant-numeric:tabular-nums; white-space:nowrap; font-size:0.78rem; }
|
||||
.l-day { display:block; font-size:0.68rem; opacity:0.8; }
|
||||
.l-rule, .l-folder { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
||||
@@ -375,11 +378,11 @@ function renderLogs() {
|
||||
? `<div class="l-mail"><b>${esc(log.mail_subject || '(kein Betreff)')}</b>${log.mail_from ? ` · <a class="flink" onclick="event.stopPropagation(); addFilter('sender', ${jsArg(emailOf(log.mail_from))})" title="Nach diesem Absender filtern">${esc(log.mail_from)}</a>` : ''}</div>`
|
||||
: '';
|
||||
html += `
|
||||
<div class="l lv-${esc(log.level)}" onclick="toggleDetail(this, ${log.id})">
|
||||
<div class="l lv-${esc(log.level)}${log.retried_at ? ' retried' : ''}" onclick="toggleDetail(this, ${log.id})">
|
||||
<span class="l-time">${day ? `<span class="l-day">${day}</span>` : ''}${time}</span>
|
||||
<span title="${esc(log.level)}">${LEVEL_ICON[log.level] || ''}</span>
|
||||
<span class="l-rule">${log.rule_name ? `<a class="flink" onclick="event.stopPropagation(); addFilter('rule', ${jsArg(log.rule_name)})" title="Nach dieser Regel filtern">${esc(log.rule_name)}</a>` : '<span class="muted">—</span>'}</span>
|
||||
<span class="l-main"><div class="l-msg">${esc(shortMessage(log))}</div>${mail}</span>
|
||||
<span class="l-main"><div class="l-msg">${log.retried_at ? `<span class="retried-tag" title="Mit „Fehlgeschlagene neu einlesen“ erneut angestoßen. Scheitert es wieder, erscheint ein neuer Fehler-Eintrag.">↻ erneut versucht ${esc(fmtShort(log.retried_at))}</span> ` : ''}${esc(shortMessage(log))}</div>${mail}</span>
|
||||
<span class="l-folder">${target.filter ? `<a class="flink" onclick="event.stopPropagation(); addFilter('folder', ${jsArg(target.filter)})" title="Nach diesem Ordner filtern">${esc(target.text)}</a>` : esc(target.text)}</span>
|
||||
</div>`;
|
||||
}
|
||||
@@ -405,6 +408,7 @@ function toggleDetail(row, id) {
|
||||
['Ordner', log.folder],
|
||||
['Mail-UID', log.mail_uid],
|
||||
['Details', log.details],
|
||||
['Erneut versucht', log.retried_at ? parseUtc(log.retried_at).toLocaleString('de-DE') : ''],
|
||||
].filter(([, v]) => v);
|
||||
const div = document.createElement('div');
|
||||
div.className = 'l-detail';
|
||||
@@ -435,12 +439,20 @@ async function clearLogs() {
|
||||
|
||||
async function retryFailed() {
|
||||
document.querySelector('.head-menu').open = false;
|
||||
if (!confirm('Alle Mails, bei denen Abrufen oder eine Aktion (z.B. Verschieben) fehlgeschlagen ist, für den nächsten Poll neu vormerken?')) return;
|
||||
if (!confirm('Alle offenen Fehler (Abrufen oder Aktion, z.B. Verschieben) beim nächsten Poll erneut versuchen?\n\nDie Einträge werden als „erneut versucht“ markiert. Scheitert eine Mail wieder, erscheint ein neuer Fehler-Eintrag.')) return;
|
||||
const acc = document.getElementById('log-account').value;
|
||||
const resp = await fetch(`/api/filters/retry-failed${acc ? `?account_id=${acc}` : ''}`, {method: 'POST'});
|
||||
const d = await readJson(resp);
|
||||
if (!resp.ok) { alert('Fehler: ' + (d.detail || resp.status)); return; }
|
||||
alert(`${d.unique_uids || 0} Mail(s) neu vorgemerkt. Werden beim nächsten Poll erneut geprüft.`);
|
||||
alert(d.log_entries
|
||||
? `${d.unique_uids} Mail(s) aus ${d.log_entries} offenen Fehler-Einträgen neu vorgemerkt. Sie werden beim nächsten Poll erneut verarbeitet.`
|
||||
: 'Keine offenen Fehler — alle wurden bereits erneut versucht.');
|
||||
reload();
|
||||
}
|
||||
|
||||
function fmtShort(iso) {
|
||||
const d = parseUtc(iso);
|
||||
return d.toLocaleDateString('de-DE', {day: '2-digit', month: '2-digit'}) + ' ' + d.toLocaleTimeString('de-DE', {hour: '2-digit', minute: '2-digit'});
|
||||
}
|
||||
|
||||
function fmtBytes(n) {
|
||||
|
||||
Reference in New Issue
Block a user