mirror of
https://github.com/juherr/kill-the-news.git
synced 2026-06-21 06:13:48 +00:00
fix(admin): make bulk delete retry safe + clarify copyable errors
This commit is contained in:
+44
-23
@@ -1265,7 +1265,7 @@ app.get("/", async (c) => {
|
|||||||
return confirm(
|
return confirm(
|
||||||
'Delete ' +
|
'Delete ' +
|
||||||
selected +
|
selected +
|
||||||
' selected feed(s)? This will also delete all emails inside those feeds.' +
|
' selected feed(s)? This disables the feeds immediately. Stored emails are cleaned up best-effort and may take a while.' +
|
||||||
extra,
|
extra,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1376,32 +1376,53 @@ app.get("/", async (c) => {
|
|||||||
updateFeedMatchCount();
|
updateFeedMatchCount();
|
||||||
updateFeedSelectionState();
|
updateFeedSelectionState();
|
||||||
|
|
||||||
// If a batch fails for some feeds, retry those one-by-one using the single delete endpoint.
|
// If a batch fails for some feeds, retry those one-by-one using the bulk-delete
|
||||||
if (failedIds.length > 0) {
|
// endpoint with a single id (keeps semantics consistent and avoids hiding active feeds).
|
||||||
|
if (failedIds.length > 0) {
|
||||||
if (toast && toast.update) {
|
if (toast && toast.update) {
|
||||||
toast.update('Retrying ' + failedIds.length + ' failed feed(s) one-by-one...', { type: 'info' });
|
toast.update('Retrying ' + failedIds.length + ' failed feed(s) one-by-one...', { type: 'info' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const stillFailed = [];
|
const stillFailed = [];
|
||||||
for (let j = 0; j < failedIds.length; j++) {
|
for (let j = 0; j < failedIds.length; j++) {
|
||||||
const feedId = String(failedIds[j] || '');
|
const feedId = String(failedIds[j] || '');
|
||||||
if (!feedId) continue;
|
if (!feedId) continue;
|
||||||
try {
|
try {
|
||||||
const retryRes = await fetch('/admin/feeds/' + encodeURIComponent(feedId) + '/delete?view=table', {
|
const retryRes = await fetch('/admin/feeds/bulk-delete', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Accept': 'application/json' },
|
headers: {
|
||||||
credentials: 'same-origin',
|
'Content-Type': 'application/json',
|
||||||
});
|
'Accept': 'application/json',
|
||||||
if (window.parseJsonResponseOrThrow) {
|
},
|
||||||
await window.parseJsonResponseOrThrow(retryRes, { prefix: 'Retry delete failed' });
|
credentials: 'same-origin',
|
||||||
} else if (!retryRes.ok) {
|
body: JSON.stringify({ feedIds: [feedId] }),
|
||||||
throw new Error('Retry delete failed (HTTP ' + retryRes.status + ')');
|
});
|
||||||
}
|
|
||||||
removeFeedRowsById([feedId]);
|
let retryData = {};
|
||||||
deletedTotal += 1;
|
if (window.parseJsonResponseOrThrow) {
|
||||||
} catch (e) {
|
retryData = await window.parseJsonResponseOrThrow(retryRes, { prefix: 'Retry delete failed' });
|
||||||
stillFailed.push(feedId);
|
} else {
|
||||||
}
|
retryData = await retryRes.json().catch(() => ({}));
|
||||||
|
if (!retryRes.ok) {
|
||||||
|
const message = retryData && retryData.error ? String(retryData.error) : ('Retry delete failed (HTTP ' + retryRes.status + ')');
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const retryDeleted = Array.isArray(retryData.deletedFeedIds) ? retryData.deletedFeedIds : [];
|
||||||
|
const retryFailed = Array.isArray(retryData.failedFeedIds) ? retryData.failedFeedIds : [];
|
||||||
|
|
||||||
|
if (retryDeleted.includes(feedId)) {
|
||||||
|
removeFeedRowsById([feedId]);
|
||||||
|
deletedTotal += 1;
|
||||||
|
} else if (retryFailed.includes(feedId)) {
|
||||||
|
stillFailed.push(feedId);
|
||||||
|
} else {
|
||||||
|
stillFailed.push(feedId);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
stillFailed.push(feedId);
|
||||||
|
}
|
||||||
|
|
||||||
if (toast && toast.update) {
|
if (toast && toast.update) {
|
||||||
toast.update('Retrying... (' + (j + 1) + ' of ' + failedIds.length + ')', { type: 'info' });
|
toast.update('Retrying... (' + (j + 1) + ' of ' + failedIds.length + ')', { type: 'info' });
|
||||||
|
|||||||
Reference in New Issue
Block a user