Content Enricher
Un message EDI ne porte presque jamais tout ce dont l'aval a besoin. Le Content Enricher remplit les vides en consultant un référentiel externe : GLN → adresse, GTIN → libellé, code pays → nom long. Le pattern de l'injection de contexte.
Problème
Les messages EDIFACT et X12 sont conçus pour être compacts : ils portent des identifiants (GLN sur 13 chiffres, GTIN sur 13 chiffres, SIRET sur 14) plutôt que des libellés. Le partenaire émetteur s'attend à ce que le récepteur sache résoudre ces identifiants vers les informations associées — nom, adresse, TVA, catégorie produit. Mais quand on alimente un ERP, un système de facturation ou un portail fournisseur, on a souvent besoin de ces champs en clair. Sans enrichissement, on doit faire ces lookups à 200 endroits dans le code aval.
Forces
- Compacité du protocole vs richesse de l'application. EDIFACT optimise la bande passante des années 80. L'application moderne veut tout en clair.
- Source de vérité externe. Le référentiel (Master Data Management, ERP) est l'autorité — pas le message qui transite.
- Coût des lookups. Chaque lookup a un coût (latence, réseau). À l'échelle d'un ORDERS avec 200 lignes, 200 lookups séquentiels deviennent prohibitifs.
- Cohérence temporelle. Le nom associé à un GLN peut changer (rebranding, fusion). On doit donc choisir entre figer l'enrichissement au moment de la réception ou re-résoudre à la consultation.
Solution
EIP §336 (Hohpe & Woolf, 2003) modélise le Content Enricher comme un composant qui : (a) reçoit un message canonique, (b) extrait les identifiants à enrichir, (c) consulte un référentiel externe, (d) injecte les champs résolus dans le message et (e) republie. La consultation peut être synchrone (lookup immédiat) ou asynchrone (pré-cache mis à jour par flux séparé).
ORDERS canonique Content Enricher ORDERS enrichi
(GLN seul) (resolves GLN → addr)
───────────── ───────────────── ───────────────
{ {
"buyer": { ┌─────────────┐ "buyer": {
"gln": "871234..." ──▶ external │ "gln": "871234...",
} │ partner-db │ "name": "Carrefour",
} │ ├──▶ "address": {
└─────────────┘ "street": "...",
"city": "Massy",
"country": "FR"
}
}
} Topologie
Trois variantes principales :
- Synchronous Enricher. Lookup à chaque message. Simple, mais sensible à la latence et à la disponibilité du référentiel.
- Cached Enricher. Lookup avec cache TTL (10 minutes à 24 heures selon le domaine). Réduit drastiquement la charge sur le référentiel.
- Pre-loaded Enricher. Réplique locale du référentiel maintenue à jour par changefeed (CDC, événements master data). Latence quasi-nulle, mais nécessite une infrastructure d'événementiel maître.
Implémentation EDI
Trois enrichissements emblématiques :
- GLN → partner record. Le partenaire envoie
NAD+BY+8712345600014::9. L'enricher résout vers une fiche partenaire avec nom, adresse, IBAN, TVA, contact. La table de résolution est typiquement la base des fournisseurs/clients de l'ERP. - GTIN → produit. Le partenaire envoie
LIN+1++4006381333931:EN. L'enricher résout vers une fiche produit avec libellé, catégorie, conditionnement, taux de TVA. La table de résolution est le catalogue produits (PIM). - Code pays ISO 3166 → nom + zone fiscale. Le
message porte
FR; l'enricher injecte « France », zone EU, code monétaire EUR par défaut. Cas du référentiel statique embarqué (pas besoin de lookup externe).
Avant enrichissement :
{
"type": "ORDER",
"number": "PO-12345",
"buyer": { "gln": "8712345600014" },
"supplier": { "gln": "5412345600015" },
"lines": [
{ "item": { "gtin": "4006381333931" }, "quantity": 24 }
]
} Après enrichissement :
{
"type": "ORDER",
"number": "PO-12345",
"buyer": {
"gln": "8712345600014",
"name": "Carrefour Centrale Massy",
"address": {
"street": "33 Avenue Émile Zola",
"city": "Massy",
"postalCode": "91300",
"country": "FR"
},
"vatId": "FR12652014051"
},
"supplier": {
"gln": "5412345600015",
"name": "Brasserie XY",
"vatId": "BE0405841683"
},
"lines": [
{
"item": {
"gtin": "4006381333931",
"name": "Pelikan rollerball ink black",
"category": "stationery"
},
"quantity": 24
}
]
} Cache, fraîcheur et politique d'échec
Trois questions à trancher :
- Quel TTL ? Pour les données partenaires relativement stables (nom, adresse), 24 heures est raisonnable. Pour des données plus volatiles (prix produit, stock), 5-15 minutes ou pas de cache.
- Que faire si le lookup échoue ? Trois
options : (a) bloquer le message en Dead Letter Channel
pour examen, (b) passer le message en aval sans enrichissement avec
un flag
enrichmentSkipped: true, (c) appliquer une valeur par défaut documentée. La bonne réponse dépend du criticité métier. - Quoi figer dans le message ? Si l'ordre doit survivre à un changement de référentiel (un GLN qui change de nom), figer le snapshot des champs enrichis. Sinon, ne stocker que l'identifiant et re-résoudre à la lecture.
Anti-patterns
- Lookup synchrone sans timeout. Si le référentiel met 30 secondes à répondre, on bloque le pipeline EDI pour 30 secondes. Toujours définir un timeout strict (1-3 secondes) avec circuit breaker.
- Lookup dans une boucle. 200 lignes = 200 appels séquentiels = inacceptable. Bulk lookup obligatoire.
- Pas de cache. Pour les données stables, ne pas cacher c'est multiplier inutilement la charge sur l'ERP.
- Cache sans invalidation. Un cache 24h sans mécanisme d'invalidation propagera une donnée obsolète pendant 24h après un changement maître. Si le référentiel publie des événements de mutation, l'enricher doit y être abonné.
- Enrichissement en silence partiel. Si seule la moitié des champs a pu être résolue, le message doit le signaler explicitement. Le consommateur aval doit voir la trace de l'incomplétude.
Patterns liés
- Canonical Model — le canonique doit prévoir les champs optionnels pour les données enrichies.
- Circuit Breaker — protéger le pipeline contre une panne du référentiel.
- Content-Based Router — souvent placé après l'enrichissement, parce que la décision a besoin des champs résolus.
Sources
- Hohpe G., Woolf B. — Enterprise Integration Patterns, pattern Content Enricher (§336). enterpriseintegrationpatterns.com — Content Enricher
- GS1 General Specifications, section 3 — Global Location Number (GLN) et Global Trade Item Number (GTIN). La référence des identifiants à enrichir. gs1.org — General Specifications
- ISO 3166-1. Codes pays et leur mapping vers les noms longs.
- AWS Architecture Blog — Caching strategies for ETL pipelines. Patterns modernes de cache TTL et invalidation par changefeed. aws.amazon.com/blogs/architecture