fix analyzer + api boundary + perf + scheduler hardening
- analyzer: rewrite checkAudioOrderChanged to compare actual output order, unify assignTargetOrder with a shared sortKeptStreams util in ffmpeg builder
- review: recompute is_noop via full audio removed/reordered/transcode/subs check on toggle, preserve custom_title across rescan by matching (type,lang,stream_index,title), batch pipeline transcode-reasons query to avoid N+1
- validate: add lib/validate.ts with parseId + isOneOf helpers; replace bare Number(c.req.param('id')) with 400 on invalid ids across review/subtitles
- scan: atomic CAS on scan_running config to prevent concurrent scans
- subtitles: path-traversal guard — only unlink sidecars within the media item's directory; log-and-orphan DB entries pointing outside
- schedule: include end minute in window (<= vs <)
- db: add indexes on review_plans(status,is_noop), stream_decisions(plan_id), media_items(series_jellyfin_id,series_name,type), media_streams(item_id,type), subtitle_files(item_id), jobs(status,item_id)
This commit is contained in:
@@ -43,16 +43,18 @@ app.get('/', (c) => {
|
||||
// ─── Start ────────────────────────────────────────────────────────────────────
|
||||
|
||||
app.post('/start', async (c) => {
|
||||
if (getConfig('scan_running') === '1') {
|
||||
const db = getDb();
|
||||
// Atomic claim: only succeed if scan_running is not already '1'.
|
||||
const claim = db.prepare("UPDATE config SET value = '1' WHERE key = 'scan_running' AND value != '1'").run();
|
||||
if (claim.changes === 0) {
|
||||
return c.json({ ok: false, error: 'Scan already running' }, 409);
|
||||
}
|
||||
|
||||
const body = await c.req.json<{ limit?: number }>().catch(() => ({}));
|
||||
const body = await c.req.json<{ limit?: number }>().catch(() => ({ limit: undefined }));
|
||||
const formLimit = body.limit ?? null;
|
||||
const envLimit = process.env.SCAN_LIMIT ? Number(process.env.SCAN_LIMIT) : null;
|
||||
const limit = formLimit ?? envLimit ?? null;
|
||||
setConfig('scan_limit', limit != null ? String(limit) : '');
|
||||
setConfig('scan_running', '1');
|
||||
|
||||
runScan(limit).catch((err) => {
|
||||
logError('Scan failed:', err);
|
||||
|
||||
Reference in New Issue
Block a user