Add maintenance: purge orphaned source image KV entries

When a source image file is deleted without going through the API
(e.g. the old bin delete bug), the KV entry remains and shows a
broken image. The new maintenance action scans all source image
entries, removes any whose file is missing on disk, and reports
how many were cleaned up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 03:08:38 +00:00
parent b200a7ec8d
commit 1aa7350c4d
4 changed files with 35 additions and 2 deletions

View File

@@ -2509,6 +2509,25 @@ async function init() {
}
});
document.getElementById('maint-purge-sources').addEventListener('click', async () => {
maint_dropdown.hidden = true;
maint_toggle.textContent = '⏳';
maint_toggle.disabled = true;
try {
const result = await api.maintenance_purge_missing_sources();
if (result.removed.length > 0) {
all_sources = all_sources.filter(s => !result.removed.includes(s.id));
render();
}
alert(`Removed ${result.removed.length} orphaned entr${result.removed.length === 1 ? 'y' : 'ies'} of ${result.total} checked.`);
} catch (err) {
alert(`Error: ${err.message}`);
} finally {
maint_toggle.textContent = '⚙';
maint_toggle.disabled = false;
}
});
window.addEventListener('popstate', () => { parse_url(); render(); });
await load_all();

View File

@@ -23,6 +23,7 @@
<button class="maint-toggle" id="maint-toggle" title="Maintenance"></button>
<div class="maint-dropdown" id="maint-dropdown" hidden>
<button class="maint-item" id="maint-gen-thumbs">Generate missing PDF thumbnails</button>
<button class="maint-item" id="maint-purge-sources">Remove orphaned source image entries</button>
</div>
</div>
</header>

View File

@@ -86,7 +86,8 @@ export async function upload_bin(file, name) {
}
// Maintenance
export const maintenance_pdf_thumbs = () => req('POST', '/api/maintenance/pdf-thumbs');
export const maintenance_pdf_thumbs = () => req('POST', '/api/maintenance/pdf-thumbs');
export const maintenance_purge_missing_sources = () => req('POST', '/api/maintenance/purge-missing-sources');
// Grid images
export const get_grids = () => req('GET', '/api/grid-images');