fix re-extract: add heartbeat yield, batch index writes, handle HTTP errors in UI

- Generator now yields a 'status' event immediately so the client can
  distinguish 'working' from 'failed silently before first event'
- Batch mode: call write_activity per file but write index.json and
  athlete.json only once at the end (was O(n²) — 2015 rewrites)
- JS: check r.ok before reading the body stream; show HTTP error detail
  instead of staying stuck at 'Starting…'
- Handle 'status' event type in the progress log
This commit is contained in:
Davide Scaini
2026-04-15 08:57:21 +02:00
parent 89b92397cf
commit 378cba85ad
2 changed files with 55 additions and 13 deletions
+9 -5
View File
@@ -190,13 +190,15 @@ import Base from '../../layouts/Base.astro';
let imported = 0, skipped = 0, errors = 0;
try {
const es = new EventSource(`/api/admin/users/${h}/reextract-originals`);
// EventSource only does GET; use fetch + ReadableStream instead
es.close();
const r = await fetch(`/api/admin/users/${h}/reextract-originals`, {
method: 'POST', credentials: 'include',
});
if (!r.ok) {
const errText = await r.text().catch(() => r.status.toString());
reextractSummary.textContent = `Error ${r.status}: ${errText}`;
reextractClose.disabled = false;
return;
}
const reader = r.body!.getReader();
const decoder = new TextDecoder();
let buf = '';
@@ -210,7 +212,9 @@ import Base from '../../layouts/Base.astro';
const dataLine = chunk.split('\n').find(l => l.startsWith('data: '));
if (!dataLine) continue;
const ev = JSON.parse(dataLine.slice(6));
if (ev.type === 'progress') {
if (ev.type === 'status') {
reextractSummary.textContent = ev.message;
} else if (ev.type === 'progress') {
const color = ev.status === 'imported' ? 'text-green-400'
: ev.status === 'error' ? 'text-red-400'
: 'text-zinc-500';