Phase 1: lock cron, reload chaud, argon2, providers, IMDb lookup, cache LRU, /health, /metrics, rate limit, UI dark, biome
This commit is contained in:
@@ -7,15 +7,13 @@
|
||||
// 3. Walk through every numeric id < max(tmdbs) and remove orphan files that
|
||||
// no longer appear in the master list.
|
||||
|
||||
import { createReadStream, createWriteStream, existsSync, statSync, readdirSync, unlinkSync } from 'node:fs';
|
||||
import { mkdir, stat, writeFile, unlink } from 'node:fs/promises';
|
||||
import { createInterface } from 'node:readline';
|
||||
import { createReadStream, existsSync, readdirSync, statSync, unlinkSync } from 'node:fs';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import {
|
||||
TMDBINTEGRAL_DIR, MOVIE_DIR, TV_DIR, TMDB_API_KEY, TMDB_API_BASE, CHANGES_DAYS,
|
||||
} from '../config.js';
|
||||
import { createInterface } from 'node:readline';
|
||||
import { CHANGES_DAYS, MOVIE_DIR, TMDB_API_BASE, TMDB_API_KEY, TMDBINTEGRAL_DIR, TV_DIR } from '../config.js';
|
||||
import { fetchJson, Limiter } from '../lib/http.js';
|
||||
import { entryDir, entryPath, bucket } from '../lib/paths.js';
|
||||
import { bucket, entryDir, entryPath } from '../lib/paths.js';
|
||||
|
||||
const CHANGES_SECS = CHANGES_DAYS * 24 * 3600;
|
||||
const DOWNLOAD_CONCURRENCY = 16;
|
||||
@@ -63,7 +61,11 @@ async function findChanges(type) {
|
||||
const path = entryPath(type, id);
|
||||
if (!existsSync(path)) continue;
|
||||
let st;
|
||||
try { st = statSync(path); } catch { continue; }
|
||||
try {
|
||||
st = statSync(path);
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
// PHP uses filectime; on Linux ctime tracks metadata changes too, but the
|
||||
// intent is "last time the local file was refreshed". We use mtime which
|
||||
// is closer to that intent in JS (writeFile updates mtime).
|
||||
@@ -72,7 +74,9 @@ async function findChanges(type) {
|
||||
const days = Math.floor(ageSecs / 86400);
|
||||
const hours = Math.floor((ageSecs % 86400) / 3600);
|
||||
const minutes = Math.floor((ageSecs % 3600) / 60);
|
||||
console.log(`Updating: "${type}/${bucket(id)}/${id}.json" ${days} days, ${hours} hours, ${minutes} minutes`);
|
||||
console.log(
|
||||
`Updating: "${type}/${bucket(id)}/${id}.json" ${days} days, ${hours} hours, ${minutes} minutes`,
|
||||
);
|
||||
updates.add(id);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +94,9 @@ async function readMasterIds(type) {
|
||||
try {
|
||||
const obj = JSON.parse(line);
|
||||
if (typeof obj.id === 'number') ids.push(obj.id);
|
||||
} catch { /* ignore malformed lines */ }
|
||||
} catch {
|
||||
/* ignore malformed lines */
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
@@ -121,10 +127,18 @@ function removeOrphans(type, sortedIds) {
|
||||
const baseDir = type === 'movie' ? MOVIE_DIR : TV_DIR;
|
||||
const expected = new Set(sortedIds);
|
||||
let buckets;
|
||||
try { buckets = readdirSync(baseDir); } catch { return; }
|
||||
try {
|
||||
buckets = readdirSync(baseDir);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
for (const b of buckets) {
|
||||
let entries;
|
||||
try { entries = readdirSync(join(baseDir, b)); } catch { continue; }
|
||||
try {
|
||||
entries = readdirSync(join(baseDir, b));
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
for (const fname of entries) {
|
||||
if (!fname.endsWith('.json')) continue;
|
||||
const id = parseInt(fname.slice(0, -5), 10);
|
||||
@@ -132,7 +146,11 @@ function removeOrphans(type, sortedIds) {
|
||||
if (!expected.has(id)) {
|
||||
const p = join(baseDir, b, fname);
|
||||
console.log(`Removing: "${type}/${b}/${fname}"`);
|
||||
try { unlinkSync(p); } catch { /* ignore */ }
|
||||
try {
|
||||
unlinkSync(p);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user