-- 016_updated_at_only_on_change.sql -- Corrige la boucle de ré-enrichissement infinie. -- -- Le trigger bands_set_geom (migration 002) faisait `NEW.updated_at := now()` -- de façon INCONDITIONNELLE sur toute UPDATE. Or upsert_bands (crawler) fait un -- `ON CONFLICT (ma_id) DO UPDATE SET name = COALESCE(EXCLUDED.name, bands.name), ...` -- SANS clause WHERE : Postgres exécute donc l'UPDATE (et déclenche le trigger) -- pour chaque ligne existante, même quand AUCUNE valeur ne change réellement. -- -- Conséquence : chaque crawl incrémental/complet remettait updated_at=now() sur -- des dizaines de milliers de bands inchangées. get_bands_to_enrich considérait -- alors `updated_at > crawled_at + 1 min` comme vrai pour quasi toute la table, -- ré-enrichissant en boucle des pages inchangées → charge inutile et permanente -- vers metal-archives.com. -- -- Fix : ne bumper updated_at que si la ligne change VRAIMENT (NEW IS DISTINCT -- FROM OLD). Un upsert qui réécrit des valeurs identiques ne déclenche plus rien. CREATE OR REPLACE FUNCTION bands_set_geom() RETURNS trigger AS $$ BEGIN -- Ne recalculer geom que si lat ou lon a vraiment changé IF TG_OP = 'INSERT' OR OLD.lat IS DISTINCT FROM NEW.lat OR OLD.lon IS DISTINCT FROM NEW.lon THEN IF NEW.lat IS NOT NULL AND NEW.lon IS NOT NULL THEN NEW.geom := ST_SetSRID(ST_MakePoint(NEW.lon, NEW.lat), 4326)::geography; ELSE NEW.geom := NULL; END IF; END IF; -- Ne bumper updated_at que sur changement réel de la ligne. -- À ce stade NEW.updated_at == OLD.updated_at (pas encore modifié), donc la -- comparaison ne se compare pas elle-même ; si toutes les autres colonnes sont -- identiques, NEW IS DISTINCT FROM OLD est faux et updated_at reste inchangé. IF TG_OP = 'INSERT' OR NEW IS DISTINCT FROM OLD THEN NEW.updated_at := now(); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_bands_set_geom ON bands; CREATE TRIGGER trg_bands_set_geom BEFORE INSERT OR UPDATE ON bands FOR EACH ROW EXECUTE FUNCTION bands_set_geom();