metalfrom.eu/apps/api/migrations/017_enrich_pending_signal.sql
Nicolas FRYDER aa4ef68dd8 fix(crawler): boucle de ré-enrichissement infinie, politesse et résilience
Le trigger bands_set_geom (migration 002) faisait `NEW.updated_at := now()`
sans condition. Or upsert_bands exécute un `ON CONFLICT DO UPDATE` sans clause
WHERE : Postgres déclenche donc le trigger pour chaque ligne vue, même quand
aucune valeur ne change. get_bands_to_enrich filtrant sur
`updated_at > crawled_at + 1 min`, la table entière redevenait « à enrichir »
après chaque crawl — le crawler repartait indéfiniment chercher des pages
inchangées sur Metal Archives.

La migration 016 ne bumpe plus updated_at que sur changement réel de la ligne.
La 017 introduit alors le signal manquant : quand MA modifie un groupe sur un
champ visible seulement sur sa page (line-up, albums), le listing ne montre
aucun diff. Le crawler capture donc l'horodatage "modified" affiché par MA
lui-même et lève enrich_pending quand ce texte change — une fois par
modification, sans boucle.

Autres correctifs :

- claim_job_trigger() réclamait n'importe quel trigger en attente. Le crawler
  raflait donc les 'geocoder_enqueue', qu'il ne sait pas exécuter, et les
  refermait en « job_type inconnu » — selon lequel des deux daemons
  interrogeait la table en premier. Borné aux CRAWLER_JOB_TYPES.
- run_enrich sautait la politesse après un échec, via un `continue` placé
  avant le sleep. Un échec de get_html étant le plus souvent un 403/429,
  c'était le pire moment pour enchaîner sans délai.
- FlareSolverrError n'était rattrapée nulle part : un blip réseau ou un crash
  du Chrome headless faisait perdre le run entier.
- La boucle du scheduler n'isolait aucune exception : une panne DB transitoire
  tuait le process, que restart: unless-stopped relançait en crash-loop.
- recover_stuck_runs() referme au démarrage les runs laissés en 'running' par
  une instance tuée brutalement.
- full_crawl publie sa progression et respire entre deux pays.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 16:43:48 +02:00

22 lines
1.2 KiB
SQL

-- 017_enrich_pending_signal.sql
-- Découple « a besoin d'être ré-enrichi » de updated_at.
--
-- Après la migration 016, updated_at ne bouge plus que sur changement réel d'un
-- champ de listing (nom, pays, genre, statut, lieu). Problème : quand Metal
-- Archives modifie un groupe sur un champ visible UNIQUEMENT sur la page du
-- groupe (line-up, albums, thèmes), la liste archives/modified ne montre aucun
-- diff au niveau listing → sans signal dédié, ce groupe ne serait ré-enrichi
-- qu'au bout de 30 jours (filet stale).
--
-- Solution : le crawler incrémental « modified » capture l'horodatage "modified"
-- que MA affiche lui-même dans sa liste (ma_modified_seen). Quand ce texte change
-- pour un groupe, on lève enrich_pending — une seule fois par modification MA,
-- sans boucle. L'enrichissement remet enrich_pending à false.
ALTER TABLE bands
ADD COLUMN IF NOT EXISTS ma_modified_seen TEXT,
ADD COLUMN IF NOT EXISTS enrich_pending BOOLEAN NOT NULL DEFAULT false;
-- Index partiel pour la file d'enrichissement (peu de lignes à true à la fois)
CREATE INDEX IF NOT EXISTS idx_bands_enrich_pending
ON bands (enrich_pending) WHERE enrich_pending;