From bd8e4e522892aae88d56daf539e1123e66481855 Mon Sep 17 00:00:00 2001 From: unfr Date: Fri, 24 Apr 2026 08:25:02 +0200 Subject: [PATCH] MAJ README : architecture, dashboard admin, hot reload, lock cron --- README.md | 75 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 923b158..17a5386 100644 --- a/README.md +++ b/README.md @@ -146,14 +146,27 @@ posters, modal de détail avec tagline/overview/budget/revenue/providers FR. Accepte requêtes texte (`Inception 2010`), IMDb IDs (`tt0133093`) et URLs TMDB collées (`themoviedb.org/movie/27205`). -### `GET /admin` -Listing protégé des fichiers du projet (mot de passe argon2id). +### `GET /admin` — Dashboard admin +SPA protégée par mot de passe (argon2id), 3 onglets, refresh automatique 10 s : + +- **Tableau de bord** — cartes de statut (dernier cron, films/séries TMDB, + notes IMDb, cache hit-rate, process), barres d'utilisation disque par + catégorie, résumé du cron (compteurs + log tail). +- **Métriques** — `/metrics` Prometheus parsé en HTML : table HTTP par route, + table latences p50/p95, compteurs internes, process Node. +- **Fichiers** — listing du projet, fichiers servis sous `/admin/files/`. + Pour générer un nouveau hash : ```bash node tools/hashPassword.js 'mon-mot-de-passe' ``` Puis copier la sortie dans `.env` sous `ADMIN_PASSWORD_HASH=`. +### Endpoints internes admin (auth requise) +- `GET /admin/api/stats` — JSON agrégé (cron, fichiers, disque, cache, process) +- `GET /admin/api/metrics` — métriques Prometheus parsées en JSON structuré +- `GET /admin/api/files` — listing des fichiers du projet en JSON + ### `GET /health` JSON liveness/readiness : status, uptime, mémoire, nombre de notes IMDb chargées. Renvoie 503 si l'index IMDb n'a pas pu être chargé. @@ -171,46 +184,52 @@ Format Prometheus standard : `http_requests_total`, `http_request_duration_secon ``` proxytmdb/ -├── server.js # Bootstrap Fastify + rate limit + sessions -├── config.js # Constantes, ports, chemins, env vars +├── server.js # Bootstrap Fastify + rate limit + sessions + warmup +├── config.js # Env vars, chemins, constantes ├── biome.json # Lint + format -├── public/ # SPA vanilla JS (UI publique) -│ ├── index.html -│ ├── style.css -│ └── app.js +├── public/ # Statique (UI publique + SPA admin) +│ ├── index.html # UI publique : recherche + grille posters + modal +│ ├── style.css # Theme dark partage +│ ├── app.js # Logique UI publique +│ ├── admin.html # SPA admin : 3 onglets +│ ├── admin.css # Styles dashboard (cartes, barres, tableaux) +│ └── admin.js # Logique dashboard + parsing metriques ├── lib/ │ ├── paths.js # Layout //.json │ ├── mbLevenshtein.js # Levenshtein UTF-8 par codepoint │ ├── titleFilter.js # Translit ligatures + filtre Latin/chiffres │ ├── queryParser.js # Extraction annee/episode/titre -│ ├── imdbRatings.js # Index IMDb en memoire (Map) -│ ├── imdbMapping.js # Mapping IMDb -> TMDb id -│ ├── http.js # fetch + retry + concurrence limitee -│ ├── format.js # Devises et runtime -│ ├── lockFile.js # Lock file PID-based pour le cron +│ ├── imdbRatings.js # Index IMDb en memoire (Map, auto-reload mtime) +│ ├── imdbMapping.js # Mapping IMDb -> TMDb id (+ preload au boot) +│ ├── http.js # fetch + retry + Limiter de concurrence +│ ├── format.js # Devises (Intl) + runtime +│ ├── lockFile.js # Lock PID-based pour le cron (O_EXCL) │ ├── password.js # Argon2id hash + verify -│ ├── metrics.js # Counters/Histograms Prometheus -│ ├── searchEngine.js # Pool workers + watcher reload chaud +│ ├── metrics.js # Counters/Histograms/Gauges Prometheus +│ ├── stats.js # Agregateur stats admin (TTL cache) +│ ├── dataReload.js # Hot reload post-cron (chunks/mappings/ratings) +│ ├── searchEngine.js # Pool workers persistants + reloadAllPools() │ └── searchWorker.js # Worker thread (1 chunk de la base) ├── routes/ │ ├── api.js # /api (movie/tv/imdb/providers/search) + cache LRU -│ ├── admin.js # /admin (login argon2 + listing) -│ └── health.js # /health + /metrics +│ ├── search.js # /search HTML compat ancien PHP +│ ├── admin.js # /admin (login argon2 + dashboard SPA + APIs) +│ └── health.js # /health + /metrics (Prometheus) ├── cron/ │ ├── runAll.js # Pipeline complet (avec lock file) │ ├── run.sh # Wrapper nvm pour crontab │ ├── imdbRatings.js # title.ratings.tsv.gz -│ ├── tmdbExports.js # Exports quotidiens TMDB +│ ├── tmdbExports.js # Exports quotidiens TMDB (avec fallback veille) │ ├── tmdbSync.js # Sync incrementale via /changes │ ├── justwatchSync.js # /watch/providers │ ├── tmdb2imdb.js # Mappings bidirectionnels │ ├── buildSearch.js # Chunks de recherche │ └── ambiguity.js # Detection des doublons ├── tools/ -│ └── hashPassword.js # Outil CLI pour generer un hash argon2 +│ └── hashPassword.js # CLI : generer un hash argon2id ├── test/ -│ └── helpers.test.js # Tests unitaires -├── tmdbintegral/ # Donnees (gitignore) +│ └── helpers.test.js # Tests unitaires (Levenshtein, query parser, paths) +├── tmdbintegral/ # Donnees TMDB + JustWatch (gitignore) └── imdbratings.tsv # Donnees IMDb (gitignore) ``` @@ -241,10 +260,20 @@ sans année) — top-N IDs identiques dans le même ordre. de recherche** générés par le cron. Le serveur en charge un par worker au démarrage (mémoire résidente, ~120 Mo total). - L'index IMDb (`imdbratings.tsv`, ~30 Mo, 1.66M lignes) est chargé une fois - en `Map` au démarrage et rechargé automatiquement quand son `mtime` change - (typiquement après le cron quotidien). + en `Map` au démarrage. Les mappings IMDb→TMDB (`imdb2movie.json` / + `imdb2tv.json`, ~16 Mo combinés) sont préchargés au warmup. +- **Hot reload post-cron** : un watcher unifié ([lib/dataReload.js](lib/dataReload.js)) + déclenche en arrière-plan le rechargement des 3 sources de données dès que + les fichiers changent — `fs.watch` (inotify) pour les chunks et mappings, + `fs.watchFile` (poll 10s) pour `imdbratings.tsv`. **Aucun redémarrage du + serveur n'est nécessaire après le cron quotidien.** - Le layout disque `//.json` est conservé à l'identique de l'ancienne version PHP : on peut basculer sans regénérer les ~1700 dossiers x 1000 fichiers existants. - Les 8 workers de recherche sont persistants (vs PHP qui forkait 8 processus à chaque requête). Gain mesuré : ~30% sur le temps de réponse. +- Le cron utilise un **lock file PID** (`.cron.lock`) — si le précédent run + n'est pas terminé (ou tourne toujours), le suivant échoue proprement. +- Logs cron : `cron.txt` (start/finish dates) + `lastcron.txt` (sortie + complète stdout, redirigée par crontab). Les deux sont gitignored et + régénérés à chaque run.