Restart failed saves through a guarded server retry
This commit is contained in:
28
server/download-retry.js
Normal file
28
server/download-retry.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// Explicit user retries bypass a failed cache row's backoff, not disk guards.
|
||||
export function registerDownloadRetryRoute(app, { media, priority, clearHints = () => {}, now = Date.now, log = console }) {
|
||||
const recent = new Map();
|
||||
app.post('/api/download/:videoId/retry', async c => {
|
||||
const id = (c.req.param('videoId') || '').trim();
|
||||
const headers = { 'Cache-Control': 'no-store' };
|
||||
if (!/^[A-Za-z0-9_-]{11}$/.test(id)) return c.json({ ok: false, error: 'invalid video id' }, 400, headers);
|
||||
// Already-ready and active jobs are reusable, so Retry never deletes a
|
||||
// playable copy or spawns a second downloader for the same song.
|
||||
const status = await media.status(id);
|
||||
if (status.status === 'ready' || status.status === 'queued' || ['downloading', 'validating'].includes(status.status)) {
|
||||
clearHints(id);
|
||||
return c.json({ ok: true, state: status.status === 'ready' ? 'ready' : 'working' }, 200, headers);
|
||||
}
|
||||
const time = now();
|
||||
if (recent.has(id) && time - recent.get(id) < 15_000) {
|
||||
return c.json({ ok: false, error: 'Please wait a few seconds before trying again.' }, 429, { ...headers, 'Retry-After': '15' });
|
||||
}
|
||||
recent.set(id, time);
|
||||
if (recent.size > 2000) for (const [key, at] of recent) if (time - at >= 15_000) recent.delete(key);
|
||||
if (recent.size > 2000) recent.delete(recent.keys().next().value);
|
||||
clearHints(id);
|
||||
// The existing cache owns the asynchronous job and deduplicates races.
|
||||
// Its normal USB-volume, free-space, size and validation checks still run.
|
||||
media.ensureCached(id, { priority, force: true }).catch(error => log.warn?.(`[download retry] ${id}: ${error.message}`));
|
||||
return c.json({ ok: true, state: 'working' }, 202, headers);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user