← Retour aux articles
Performance et bases de données

Event Sourcing en pratique : pas seulement du versioning de données, mais un puissant outil d'analytique

Un guide pratique du pattern Event-Sourced Entity en Laravel : pistes d'audit complètes, reconstruction à un instant précis et pourquoi les journaux d'événements sont une mine d'or pour l'analytique métier.

Event Sourcing en pratique : pas seulement du versioning de données, mais un puissant outil d'analytique
Article en vedette ↗

Event Sourcing en pratique : pas seulement du versioning de données, mais un puissant outil d'analytique

Aujourd'hui, je souhaite discuter d'un pattern architectural courant dans les applications métier complexes mais souvent sous-estimé : l'« Event-Sourced Entity » ou, plus simplement, un système robuste de versioning de données.

Qu'est-ce que c'est ?

Dans le modèle CRUD classique, nous mettons à jour un enregistrement directement dans une table comme products : price = 1000. L'historique des modifications est silencieusement perdu.

Le modèle événementiel fonctionne différemment :

  1. L'entité principale ne stocke que l'état actuel (par exemple, le dernier prix, le niveau de stock).
  2. Chaque changement (un événement) est enregistré dans une table de journal séparée en tant qu'entrée indépendante et immuable.
  3. L'état actuel est le résultat de l'application séquentielle de tous les événements historiques.

Un exemple simple en Laravel

Considérons une entité ProductPricing.

1. Migrations :

// Table principale (état actuel) Schema::create('product_pricings', function (Blueprint $table) { $table->id(); $table->foreignId('product_id')->constrained(); $table->decimal('price', 10, 2); $table->integer('stock'); $table->timestamps(); }); // Table des événements (historique) Schema::create('pricing_events', function (Blueprint $table) { $table->id(); $table->foreignId('product_pricing_id')->constrained()->onDelete('cascade'); $table->string('type'); // 'price_changed', 'stock_incremented' $table->json('payload'); // { "old_price": 100, "new_price": 120, "reason": "supplier_cost" } $table->timestamp('performed_at'); $table->foreignId('user_id')->nullable(); // Qui l'a initié });

2. Modèle et événement :

// Event Data Transfer Object class PriceChangedEvent { public function __construct( public float $oldPrice, public float $newPrice, public string $changedBy, public ?string $reason = null ) {} } // Modèle ProductPricing class ProductPricing extends Model { public function events() { return $this->hasMany(PricingEvent::class); } public function changePrice(float $newPrice, User $user, string $reason): void { // 1. Enregistrer l'événement $this->events()->create([ 'type' => 'price_changed', 'payload' => new PriceChangedEvent( oldPrice: $this->price, newPrice: $newPrice, changedBy: $user->email, reason: $reason ), 'performed_at' => now(), 'user_id' => $user->id, ]); // 2. Mettre à jour l'état actuel $this->update(['price' => $newPrice]); } }

Avantages de cette approche :

✅ Piste d'audit complète et traçabilité. Nous savons non seulement ce qui a changé, mais aussi quand, par qui et pourquoi. Inestimable pour la conformité et la résolution des litiges.

✅ Reconstruction de l'état à un instant précis. Nous pouvons « rejouer » le modèle jusqu'à n'importe quel moment passé en recalculant les événements jusqu'à ce point.

✅ Logique métier découplée. Les événements sont des faits purs. Ils peuvent être traités de manière asynchrone, envoyés à des files de messages (RabbitMQ, Kafka).

✅ Fondation pour CQRS. Le journal d'événements est une source unique de vérité parfaite pour construire divers modèles de lecture (par exemple, spécialisés pour le reporting).

Inconvénients et complexités :

❌ Complexité accrue. L'architecture devient plus complexe que le « simple CRUD ». La cohérence entre la table principale et les événements doit être gérée.

❌ Surcoût de performance. Au lieu d'une seule mise à jour, nous effectuons au moins deux écritures. Excessif pour les systèmes à haut débit où l'historique n'est pas nécessaire.

❌ Interrogation de l'historique. L'analyse des données nécessite de travailler avec de grands flux d'événements, ce qui peut être non trivial.

Où est-ce particulièrement utile ? Le cas d'usage clé : l'analytique.

Cette approche est une mine d'or pour les analystes de données et la business intelligence. Pourquoi ?

  1. Analyse des tendances et dynamiques : Construisez facilement des graphiques des changements de prix des produits dans le temps, analysez la saisonnalité et corrélez avec les campagnes marketing.
  2. Calcul de métriques : Prix moyen sur une période, taux de rotation des stocks, fréquence des ajustements.
  3. Analyse des causes profondes : Le regroupement des événements par raison ou user_id révèle ce qui motive le plus souvent les changements : fluctuations de devises, actions des concurrents, demande saisonnière.
  4. Modélisation « What-If » : Sur la base d'événements historiques, vous pouvez construire des simulations. « Que se passe-t-il pour le profit si nous augmentons le prix de X % pendant la période Y ? »

Exemple de requête SQL pour l'analytique :

-- Obtenir l'historique des prix d'un produit spécifique sur le dernier mois SELECT DATE(performed_at) as change_date, JSON_UNQUOTE(JSON_EXTRACT(payload, '$.new_price')) as price, JSON_UNQUOTE(JSON_EXTRACT(payload, '$.reason')) as change_reason FROM pricing_events WHERE product_pricing_id = 123 AND type = 'price_changed' AND performed_at >= NOW() - INTERVAL 30 DAY ORDER BY performed_at;

Conclusion

Le pattern « Event-Sourced Entity » est plus que simplement « sauvegarder l'ancienne valeur ». C'est un changement de paradigme : passer de la pensée en « états » à la pensée en « processus » et en « historique ».

Utilisez-le lorsque :

  • Des pistes d'audit législatives sont requises (pharma, finance, B2G).
  • Le processus métier est une séquence d'événements significatifs (commande : créée → payée → exécutée → expédiée).
  • Vous avez un besoin critique d'analytique approfondie sur des métriques clés changeantes (prix, stocks, taux, notes).

C'est un investissement dans l'architecture qui porte ses fruits en termes de transparence, de flexibilité et de profondeur des données pour la prise de décision.

Technologies et sujets

Tags de l'article

Aucun article ne correspond à ces filtres.

Vous avez un projet ou une idée à discuter ?

Parlons-en ↗