metalfrom.eu/apps/api/migrations/004_crawl_tracking.sql
Nicolas Fryder d2fcafc6be feat(db): système de migrations SQL + refonte schéma
- apps/api/migrations/ : 4 migrations numérotées idempotentes
  001 : schéma initial (bands, trigger geom, indexes)
  002 : colonnes manquantes (enriched, themes, geocode_*) + fix trigger
        → updated_at mis à jour sur toute UPDATE (pas seulement lat/lon)
  003 : geocode_queue et geocode_cache (formalisées)
  004 : tracking crawl (crawled_at, crawled_hash, ma_created_at,
        ma_modified_at, first_seen_at) + crawl_run + crawl_checkpoint
- apps/api/src/migrate.js : runner qui s applique au démarrage de l api
- apps/api/Dockerfile : CMD lance migrate.js avant server.js
- infra/init.sql : remplacé par notice de redirection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 15:09:35 +02:00

43 lines
2.2 KiB
SQL

-- Nouvelles colonnes sur bands pour tracker les crawls
ALTER TABLE bands ADD COLUMN IF NOT EXISTS first_seen_at TIMESTAMPTZ; -- quand on a découvert ce band pour la 1ère fois
ALTER TABLE bands ADD COLUMN IF NOT EXISTS crawled_at TIMESTAMPTZ; -- dernier crawl de la band page
ALTER TABLE bands ADD COLUMN IF NOT EXISTS crawled_hash TEXT; -- md5 du HTML de la band page (détection de changements)
ALTER TABLE bands ADD COLUMN IF NOT EXISTS ma_created_at TEXT; -- "Added" affiché par MA (texte brut, format variable)
ALTER TABLE bands ADD COLUMN IF NOT EXISTS ma_modified_at TEXT; -- "Last modified" affiché par MA
-- Backfill first_seen_at pour les bands existantes
UPDATE bands SET first_seen_at = created_at WHERE first_seen_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_bands_crawled_at ON bands (crawled_at);
CREATE INDEX IF NOT EXISTS idx_bands_first_seen ON bands (first_seen_at);
-- Historique des runs de crawl
CREATE TABLE IF NOT EXISTS crawl_run (
id BIGSERIAL PRIMARY KEY,
run_type TEXT NOT NULL, -- full_europe | incremental_additions | incremental_modified | single_band
countries TEXT[], -- codes pays ciblés (null = tous)
status TEXT NOT NULL DEFAULT 'running', -- running | done | error | cancelled
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
finished_at TIMESTAMPTZ,
bands_seen INT NOT NULL DEFAULT 0,
bands_new INT NOT NULL DEFAULT 0,
bands_updated INT NOT NULL DEFAULT 0,
bands_enriched INT NOT NULL DEFAULT 0,
error TEXT
);
CREATE INDEX IF NOT EXISTS idx_crawl_run_type_started ON crawl_run (run_type, started_at DESC);
-- État persistant des crawls (dernière date/page vérifiée, etc.)
CREATE TABLE IF NOT EXISTS crawl_checkpoint (
key TEXT PRIMARY KEY,
value TEXT,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Valeurs initiales
INSERT INTO crawl_checkpoint (key, value) VALUES
('last_additions_check', NULL), -- timestamp du dernier check de /archives/band-list/by/created
('last_modified_check', NULL), -- timestamp du dernier check de /archives/band-list/by/modified
('last_full_crawl_at', NULL) -- timestamp du dernier crawl complet Europe
ON CONFLICT (key) DO NOTHING;