Alors, qu'est-ce qui me manque?
Faire une supposition.
La première chose qui vous manque peut-être est que vous n'avez qu'à recharger les événements pour l'état que vous reconstruisez. Si vous pouvez modéliser correctement vos limites de transaction, chaque objet peut écrire des événements étiquetés avec son propre identifiant, puis relire uniquement ces événements. En utilisant une base de données relationnelle pour le stockage des événements, il y aurait une colonne id indexée pour accélérer cette requête. En utilisant EventStore, chaque objet aurait son propre flux.
Cela prend un certain soin dans votre modèle pour le faire proprement, car vous voulez être sûr que vous ne modifiez qu'un seul objet dans chaque transaction, et donc vous devez faire attention à isoler correctement chaque invariant que vous essayez de imposer.
Dans les cas où cela n'est pas assez rapide, vous avez toujours la possibilité de créer des instantanés de votre état (mémorisation) et de les conserver dans le "stockage traditionnel". Chaque instantané est étiqueté avec le numéro de séquence du dernier événement utilisé pour créer l'instantané; lors du rechargement, le référentiel récupère d'abord cet instantané, puis lui applique les événements les plus récents. (Cela implique un moyen raisonnable de récupérer les instantanés les plus récents - soit les événements sont également marqués avec le numéro de séquence, soit vous avez un moyen efficace de lire le flux d'événements en arrière jusqu'à ce que vous arriviez à votre point de départ.)
Il y a toujours un avantage sur l'approche habituelle ici, étant que vos instantanés peuvent être construits en parallèle de vos écritures, plutôt que d'être fusionnés avec eux: vous mettez simplement un écouteur d'événements dans un autre thread / processus, et le laissez gaiement en écrivant au magasin d'instantanés sur n'importe quel calendrier semble raisonnable. Après tout, l'instantané n'a pas besoin d'être particulièrement opportun - juste assez souvent pour que le travail de réapplication des événements les plus récents ne fasse pas exploser votre SLA.
(La capture instantanée complique la migration; toute modification de la sérialisation du modèle invalidera le cache de capture instantanée. Bien sûr, vous pouvez reconstruire des captures instantanées en utilisant la nouvelle sérialisation dans le cadre de la migration, puis "rattraper" lorsque les modifications seront mises en ligne.)
La restauration de l'état à partir du flux d'événements est-elle même couramment effectuée?
Oui, ça l'est. Ce qui est normalement montré dans les exemples CQRS, c'est que la couche Application, après avoir vérifié que la commande soumise est bien formée, la couche Application chargera l'objet de domaine à partir d'un référentiel, où la charge est un constructeur par défaut suivi d'une relecture du flux d'événements. (ou de manière équivalente, un appel à une usine avec une liste d'événements).
Deux autres pensées contradictoires.
- Il pourrait y avoir un cache derrière l'interface du référentiel
- L'invalidation du cache est l'un des deux problèmes difficiles.