Nous avons une architecture microservice et appliquons le modèle CQRS. Une commande envoyée à un microservice déclenche un changement d'état de l'application et l'émission de l'événement correspondant sur notre bus Kafka. Nous projetons ces événements dans un modèle de lecture construit avec ElasticSearch.
Jusqu'à présent, tout va bien.
Nos microservices sont finalement cohérents entre eux. Mais à tout moment, ils ne le sont pas (nécessairement). Par conséquent, les événements qu'ils envoient ne sont pas toujours cohérents entre eux non plus.
De plus, pour garantir la cohérence entre un changement d'état de l'application et l'émission de l'événement correspondant, nous persistons dans la DB le nouvel état et l'événement correspondant dans la même transaction (je suis conscient que nous pourrions utiliser la source d'événements et éviter de persister l'état complètement). Un travailleur asynchrone est ensuite chargé d'envoyer ces événements sur le bus Kafka. Ce modèle garantit qu'au moins un événement sera envoyé pour chaque changement d'état (ce qui n'est pas un problème puisque nos événements sont idempotents). Cependant, étant donné que chaque microservice possède sa propre table d'événements et son propre travailleur asynchrone, nous ne pouvons pas garantir que les événements seront envoyés dans l'ordre dans lequel les changements d'état correspondants se sont produits dans leurs microservices respectifs.
EDIT : pour clarifier, chaque microservice a sa propre base de données, sa propre table d'événements et son propre travailleur. Un employé spécifique traite les événements dans l'ordre dans lequel ils ont été enregistrés dans sa table d'événements correspondante, mais des employés différents sur des tables d'événements différentes, c'est-à-dire pour des microservices distincts, n'offrent pas cette garantie.
Le problème se pose lorsqu'il s'agit de projeter ces événements incohérents ou hors séquence provenant de différents microservices dans le même document ElasticSearch.
Un exemple concret : imaginons trois agrégats différents A, B et C (agrégat au sens du Domain Driven Design) gérés par différents microservices :
- Il existe une relation de plusieurs à plusieurs entre A et B. L'agrégat A fait référence aux racines de l'agrégat B auquel il est lié, mais B n'est pas conscient de ses relations avec A. Lorsque B est supprimé, le microservice gérant A est à l'écoute de l'événement correspondant et annule la liaison de A avec B.
- De même, il existe une relation "many-to-many" entre B et C. B connaît tous les agrégats de C, mais l'inverse n'est pas vrai. Lorsque C est supprimé, le microservice qui gère B est à l'écoute de l'événement correspondant et annule la liaison entre B et C.
- C a une propriété "name".
L'un des cas d'utilisation consiste à trouver, via ElasticSearch, tous les agrégats A liés à un agrégat B, lui-même lié à un agrégat C portant un nom spécifique.
Comme expliqué plus haut, les tables d'événements et les travailleurs distincts pourraient introduire des délais variables entre l'émission d'événements provenant de différents microservices. Créer A, B et C et les lier ensemble pourrait par exemple aboutir à la séquence d'événements suivante :
- B créé
- B lié à C
- C créé avec le nom XYZ
- Une création
- A lié à B
Autre exemple de lot d'événements : supposons que nous ayons initialement les agrégats B et C et que deux commandes soient émises simultanément :
- supprimer C
- lier B à C
cela pourrait entraîner les événements suivants :
- C supprimé
- B lié à C
- B délié de C (en réponse à l'événement 1)
Concrètement, nous avons du mal à projeter ces événements dans le(s) document(s) ElasticSearch car les événements font parfois référence à des agrégats qui n'existent plus ou pas encore. Toute aide serait appréciée.