0054 — Ingestion massive OpenAlex par snapshot S3 (works + authors, incrémental par updated_date)
Contexte
Section intitulée « Contexte »L’ADR 0029 a posé
l’architecture du pipeline de collaborations et prévoyait une ingestion delta
d’un sous-périmètre via l’API REST d’OpenAlex (interface web qui renvoie les
données page par page sur requête HTTP), paginée à une requête par seconde, avec
un curseur de date (from_updated_date=watermark). Le paquet citation-fetch
implémente déjà cette voie.
L’exigence a changé : il faut désormais ingérer toute la base OpenAlex — les
deux entités works (publications) et authors (chercheurs) — de façon
mensuelle et incrémentale. À cette échelle, l’API REST devient infaisable :
- Volumétrie. OpenAlex compte de l’ordre de 250 millions de
workset 90 millions d’authors. À une requête par seconde, parcourir l’ensemble prendrait des années. - Limite technique dure. Le code d’ingestion par API
(
packages/citation/src/fetch/fetch-citation.ts,count > 10000) plafonne à 10 000 résultats par requête — la pagination profonde de l’API n’autorise pas davantage. L’API ne peut donc pas servir l’ingestion massive.
OpenAlex publie, en regard de l’API, un data snapshot : une copie complète de la base, exportée en fichiers, mise à disposition sur un stockage objet public. C’est la voie retenue ici. Faits techniques (source : documentation officielle OpenAlex) :
- Bucket :
s3://openalex(programme AWS Open Data, accès anonyme sans clé d’authentification). Le terme S3 désigne le protocole de stockage objet d’Amazon, devenu un standard de fait. - Taille : environ 330 Go compressés (≈ 1,6 To décompressés).
- Arborescence :
s3://openalex/data/works/updated_date=YYYY-MM-DD/0000_part_00.gz, idem pourdata/authors/. Une partitionupdated_dateest un dossier regroupant les enregistrements modifiés à une date donnée. Les fichiers sont au format JSONL (JSON Lines : un objet JSON par ligne) compressé en gzip. manifest: un fichier par entité, sentinelle de complétude — sa présence garantit que tous les fichiers de données sont écrits (absent = export en cours).merged_ids: le dossiers3://openalex/legacy-data/merged_ids/<entity>/(fichiersYYYY-MM-DD.csv.gz, colonnesmerge_date,id,merge_into_id— confirmé à l’implémentation, étape 2.2) liste les entités fusionnées (deux identifiants OpenAlex désignant la même entité réelle, dédupliqués).fwci(Field-Weighted Citation Impact, impact de citation normalisé par domaine) etcited_by_countsont des champs portés par chaqueworkdans le snapshot — captés au passage, sans seconde ingestion.
Cadence : un fait à assumer. Le snapshot gratuit est rafraîchi trimestriellement. Les snapshots mensuels et les fichiers de changements quotidiens sont payants. Il n’existe donc pas de snapshot mensuel gratuit : cette décision n’en invente pas un (voir Décision et Prix à payer).
Décision
Section intitulée « Décision »L’ingestion de la base complète OpenAlex (
works+authors) se fait par le snapshot S3, de façon incrémentale par partitionupdated_date. L’API REST est reléguée aux compléments ciblés (moins de 10 000 résultats).
Source : le snapshot S3, pas l’API REST
Section intitulée « Source : le snapshot S3, pas l’API REST »Le pipeline synchronise s3://openalex/data/{works,authors} vers le lakehouse
souverain s3://citation/raw (bucket RGW Ceph du cluster, voir
ADR 0029 pour le
contrat de stockage). L’API REST (citation-fetch) reste disponible mais
uniquement pour des compléments ponctuels et bornés (une entité précise, une
fenêtre étroite) sous le plafond des 10 000 résultats. Elle n’est plus le chemin
d’ingestion massive.
Périmètre : works + authors
Section intitulée « Périmètre : works + authors »Les deux entités sont ingérées. Les références bibliographiques
(referenced_works, matière première du signal de citations croisées), le fwci
et le cited_by_count sont lus comme champs des works du snapshot — ils ne
nécessitent plus de passe d’ingestion séparée par l’API.
Incrémental par updated_date + watermark de date
Section intitulée « Incrémental par updated_date + watermark de date »Après le bootstrap (synchronisation initiale complète), chaque exécution ne
re-synchronise que les partitions updated_date postérieures à un watermark
de date persistant (un enregistrement modifié migre dans la partition de sa
nouvelle date). Le watermark n’avance qu’après une synchronisation complète et
réussie (idempotence : un rejeu ne corrompt pas l’état).
Transfert inter-endpoints : rclone
Section intitulée « Transfert inter-endpoints : rclone »La source (s3://openalex, endpoint AWS public) et la cible (s3://citation/raw,
endpoint RGW Ceph interne) sont deux endpoints S3 distincts ; aucun outil ne
copie nativement de l’un à l’autre par une simple commande mono-endpoint. Le
transfert est confié à rclone (outil libre de synchronisation de stockage,
licence MIT), configuré avec deux remotes : openalex (accès anonyme,
sans clé) et ceph (credentials de l’ObjectBucketClaim). rclone sync gère
nativement le transfert entre endpoints distincts, le parallélisme, la
reprise et le filtrage par préfixe (donc le sous-échantillon borné des
tests). Alternative écartée : un aws s3 cp en deux temps (téléchargement
éphémère puis ré-upload) — plus de code, pas de sync différentiel natif. rclone
est ajouté à l’image du code-location.
Entités fusionnées : merged_ids
Section intitulée « Entités fusionnées : merged_ids »À chaque incrément, les fichiers merged_ids postérieurs au watermark sont
rapatriés bruts dans raw/merged_ids/<entity>/ — comme works/authors, et
sans réécriture en place (immutabilité préservée). La fusion effective (supprimer
ou rediriger les entités dédupliquées) n’est pas faite à l’ingestion : elle est
appliquée en aval, dans les modèles dbt (étape 3), qui lisent ces fichiers. Format
confirmé (étape 2.2) : legacy-data/merged_ids/<entity>/YYYY-MM-DD.csv.gz, colonnes
merge_date,id,merge_into_id — le chemin réel (legacy-data/, non data/) est un
écart consigné comme drift D5.
Cadence réelle : trimestrielle
Section intitulée « Cadence réelle : trimestrielle »La cadence effective d’arrivée de nouvelles données est trimestrielle (limite de la source gratuite). Le planificateur (schedule) Dagster peut rester déclaré mensuel : un passage mensuel est idempotent et ne traite que d’éventuelles nouvelles partitions — entre deux trimestres, il ne trouve rien de neuf et n’écrit rien. Si une fraîcheur mensuelle réelle devient nécessaire, l’offre payante OpenAlex est l’option à arbitrer (par le déployeur). On ne prétend pas un mensuel gratuit qui n’existe pas.
s3://openalex est le bucket source externe : il n’apparaît que dans la prose.
Aucun identifiant interne d’atlas (bucket, namespace, paquet, variable, modèle)
ne porte « openalex » : la synchronisation écrit vers s3://citation/raw
(convention de dépôt, voir le plan
pipeline de collaborations).
Accepted (2026-06-10). Amende l’ADR 0029
sur le seul point de la stratégie d’ingestion : l’ingestion delta par API REST
paginée (from_updated_date=watermark, sous-périmètre) est remplacée, pour la
base complète, par le snapshot S3 (works + authors, incrémental par
updated_date). L’API REST subsiste pour les compléments ciblés (< 10 000
résultats). Le reste de 0029 (contrat Parquet + manifest, transformations dbt,
orchestration Dagster, lineage OpenLineage/Marquez, index pgvector, scoring
déterministe) demeure en vigueur.
Conséquences
Section intitulée « Conséquences »Bénéfices. Souveraineté : la source est un export public, en accès anonyme,
sans quota d’API ni clé. Exhaustivité : toute la base works + authors, pas un
sous-ensemble. Incrémentalité native : les partitions updated_date donnent le
delta sans logique de curseur applicative. Plus de plafond des 10 000 résultats.
Prix à payer. Volumétrie : ~330 Go compressés / 1,6 To décompressés à
rapatrier au bootstrap, avec l’impact correspondant sur le stockage objet Ceph
(datalake en erasure coding 2+1) et sur la durée du premier run. Cadence
trimestrielle (pas mensuelle) tant qu’on reste sur la source gratuite. Coût
des jointures dbt/DuckDB sur ce volume (works × referenced_works). Application des
merged_ids reportée en aval (dbt). Surtout : la synchronisation exige un accès
Internet sortant depuis le cluster vers les endpoints S3 d’AWS, ce qui entre en
tension avec le réseau default-deny du cluster (ADR cluster
0019) :
une politique d’egress Internet dédiée est un prérequis d’infrastructure
(tracé côté dépôt cluster).
Garde-fous. L’API REST reste plafonnée aux compléments (< 10 000) — jamais
l’ingestion massive. Les partitions du lakehouse restent immuables (un rejeu
produit un nouveau run, jamais une réécriture en place). Le contrat de
transfert producteur↔consommateur (Parquet + manifest) est inchangé : cet
ADR ne touche que l’amont (l’ingestion brute), pas l’interface DataOps↔scoring.
Le watermark de date n’avance qu’après succès complet. En test local (petit
cluster), l’échelle est bornée par configuration (un seul dossier
updated_date, ou un nombre limité de fichiers) — on ne synchronise jamais 1,6 To
sur le banc.