Loading debian/changelog +8 −0 Original line number Diff line number Diff line mediadb (20260424+79) unstable; urgency=medium * Reduce MAX_CONCURRENT_PREVIEWS 6→2 in admin.html and gallery.html to avoid H2 stream serialisation timeouts on multiplexed connections. * Retry on network errors (TypeError), not only AbortError. -- Jan Koester <jan.koester@tuxist.de> Thu, 24 Apr 2026 00:00:00 +0200 mediadb (20260424+78) unstable; urgency=medium * Fix: guard PrefetchBuffer future .wait() calls with .valid() check. Loading html/admin.html +12 −11 Original line number Diff line number Diff line Loading @@ -183,7 +183,10 @@ function fmtSize(b) { // ---- Preview loader with throttling ---- const previewQueue = []; let previewActive = 0; const MAX_CONCURRENT_PREVIEWS = 6; // Keep concurrency low: HTTP/2 multiplexes all requests on one TCP // connection and the server dispatches streams serially. With high // concurrency the last streams exceed the client timeout. const MAX_CONCURRENT_PREVIEWS = 2; const PREVIEW_TIMEOUT_MS = 45000; function drainPreviewQueue() { Loading @@ -209,16 +212,14 @@ function drainPreviewQueue() { job.img.title = 'Preview failed (HTTP ' + r.status + ')'; } }).catch(err => { if (err.name === 'AbortError') { // Timeout or manual abort — re-queue with delay // Retry on timeout (AbortError) and network errors (TypeError) job.retries = (job.retries || 0) + 1; if (job.retries < 3) { setTimeout(() => { previewQueue.push(job); drainPreviewQueue(); }, 2000); } else { job.img.alt = '\u26a0'; job.img.style.opacity = '.5'; job.img.title = 'Preview timeout'; } job.img.title = err.name === 'AbortError' ? 'Preview timeout' : 'Network error'; } }).finally(() => { clearTimeout(timer); previewActive--; drainPreviewQueue(); }); } Loading html/gallery.html +4 −6 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ const API = ''; // ---- Preview fetch throttling ---- const galQueue = []; let galActive = 0; const GAL_MAX_CONCURRENT = 6; const GAL_MAX_CONCURRENT = 2; const GAL_TIMEOUT_MS = 45000; function galDrain() { Loading @@ -71,12 +71,10 @@ function galDrain() { setTimeout(() => { galQueue.push(job); galDrain(); }, 2000); } }).catch(err => { if (err.name === 'AbortError') { job.retries = (job.retries || 0) + 1; if (job.retries < 3) { setTimeout(() => { galQueue.push(job); galDrain(); }, 2000); } } }).finally(() => { clearTimeout(timer); galActive--; galDrain(); }); } } Loading Loading
debian/changelog +8 −0 Original line number Diff line number Diff line mediadb (20260424+79) unstable; urgency=medium * Reduce MAX_CONCURRENT_PREVIEWS 6→2 in admin.html and gallery.html to avoid H2 stream serialisation timeouts on multiplexed connections. * Retry on network errors (TypeError), not only AbortError. -- Jan Koester <jan.koester@tuxist.de> Thu, 24 Apr 2026 00:00:00 +0200 mediadb (20260424+78) unstable; urgency=medium * Fix: guard PrefetchBuffer future .wait() calls with .valid() check. Loading
html/admin.html +12 −11 Original line number Diff line number Diff line Loading @@ -183,7 +183,10 @@ function fmtSize(b) { // ---- Preview loader with throttling ---- const previewQueue = []; let previewActive = 0; const MAX_CONCURRENT_PREVIEWS = 6; // Keep concurrency low: HTTP/2 multiplexes all requests on one TCP // connection and the server dispatches streams serially. With high // concurrency the last streams exceed the client timeout. const MAX_CONCURRENT_PREVIEWS = 2; const PREVIEW_TIMEOUT_MS = 45000; function drainPreviewQueue() { Loading @@ -209,16 +212,14 @@ function drainPreviewQueue() { job.img.title = 'Preview failed (HTTP ' + r.status + ')'; } }).catch(err => { if (err.name === 'AbortError') { // Timeout or manual abort — re-queue with delay // Retry on timeout (AbortError) and network errors (TypeError) job.retries = (job.retries || 0) + 1; if (job.retries < 3) { setTimeout(() => { previewQueue.push(job); drainPreviewQueue(); }, 2000); } else { job.img.alt = '\u26a0'; job.img.style.opacity = '.5'; job.img.title = 'Preview timeout'; } job.img.title = err.name === 'AbortError' ? 'Preview timeout' : 'Network error'; } }).finally(() => { clearTimeout(timer); previewActive--; drainPreviewQueue(); }); } Loading
html/gallery.html +4 −6 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ const API = ''; // ---- Preview fetch throttling ---- const galQueue = []; let galActive = 0; const GAL_MAX_CONCURRENT = 6; const GAL_MAX_CONCURRENT = 2; const GAL_TIMEOUT_MS = 45000; function galDrain() { Loading @@ -71,12 +71,10 @@ function galDrain() { setTimeout(() => { galQueue.push(job); galDrain(); }, 2000); } }).catch(err => { if (err.name === 'AbortError') { job.retries = (job.retries || 0) + 1; if (job.retries < 3) { setTimeout(() => { galQueue.push(job); galDrain(); }, 2000); } } }).finally(() => { clearTimeout(timer); galActive--; galDrain(); }); } } Loading