MAJ README : architecture, dashboard admin, hot reload, lock cron

This commit is contained in:
unfr
2026-04-24 08:25:02 +02:00
parent d767b6e581
commit bd8e4e5228

View File

@@ -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 <type>/<floor(id/1000)>/<id>.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 `<type>/<floor(id/1000)>/<id>.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.