DDD - Eventi di dominio vs eventi dell'applicazione

0

Sto prendendo in considerazione due tipi di notifiche:

  • Eventi di dominio utilizzati internamente in un contesto limitato
  • Eventi di applicazione utilizzati per scambiare messaggi di notifica tra contesti limitati

Ogni aggregato nel mio contesto limitato definisce il proprio limite di transazione, in modo tale che solo un aggregato viene modificato per transazione. Quando una transazione viene eseguita correttamente, un evento di dominio viene pubblicato in modo asincrono e internamente al fine di informare gli altri aggregati del contesto limitato che qualcosa è successo.

Alcuni servizi applicativi nel contesto limitato reagiscono a questi eventi. Ognuno aggiorna un aggregato in una transazione separata. Alla fine, tutti gli aggregati del contesto limitato sono resi alla fine coerenti.

Ho bisogno di pubblicare alcuni di questi eventi di dominio in altri contesti limitati. Ma mi sentirei più a mio agio se potessi mantenere un accoppiamento lento tra gli eventi del dominio di ogni contesto limitato e i messaggi di notifica scambiati tra i contesti limitati. Inoltre, posso prevedere situazioni in cui non esiste sempre una corrispondenza 1-1 tra eventi di dominio ed eventi applicativi, retoricamente parlando.

Allora ho alcune domande:

  • Si tratta di un utilizzo corretto degli eventi di dominio all'interno di un contesto limitato?
  • Se il contenitore / VM che ospita il contesto limitato (implementato in un micro-servizio) si arresta in modo anomalo prima che tutti gli aggregati siano resi eventualmente coerenti, ho uno stato incoerente quando il micro-servizio viene riavviato. Nel suo libro rosso, Vaughn Vernon suggerisce l'implementazione di un negozio di eventi. Ci sono molti vantaggi nell'avere un negozio di eventi, ma tra tutti questi vantaggi, aiuterà a risolvere il problema di incoerenza?
  • Devo davvero separare gli eventi di dominio dagli eventi delle applicazioni?
  • Se implemento un negozio di eventi per gli eventi del dominio, qual è la strategia migliore per trasformare questi eventi di domini in eventi applicativi e inoltrare questi eventi applicativi ad altri contesti limitati, assicurandoti che se il recapito di un messaggio di notifica fallisce, può essere riconsegnato quando necessario?
posta Stéphane Appercel 08.10.2018 - 19:14
fonte

2 risposte

0

I'm considering two types of notifications

Per una serie di ragioni, la letteratura è piuttosto debole qui; ma credo che scoprirai che la tassonomia degli "eventi del dominio" e degli "eventi di integrazione" è più diffusa dell'ortografia che stai utilizzando.

Is this a correct usage of domain events within a bounded context

Praticamente. Molti degli usi precedenti degli eventi di dominio erano gestiti da gestori che eseguivano la stessa transazione dell'aggregazione "aggregata".

Questa distinzione è importante per le altre tue domande - poiché i gestori erano in esecuzione nella stessa transazione, tutti gli aggiornamenti fallirebbero o avrebbero avuto esito positivo insieme. Ciò ha eliminato i problemi di coerenza.

There are several advantages to having an event store, but among all these advantages, will it help solving the inconsistency issue?

No; avere un negozio di eventi non risolverà questo problema. Il principale problema di coerenza che hai di fronte è una conseguenza del fatto che non stai salvando gli eventi del dominio nella transazione con l'aggregato.

Se hai gli eventi di dominio in atto e gli impianti idraulici appropriati per riprovare a consegnare tali eventi dopo un riavvio, il tuo sistema può finalmente ripristinarsi in uno stato coerente.

Vedi, ad esempio, Udi Dahan: Messaggistica affidabile senza transazioni distribuite .

    
risposta data 08.10.2018 - 21:10
fonte
2

Dopo aver visto il video di Udi Dahan, sto provando il seguente approccio:

  • Ho un archivio eventi che contiene gli eventi del dominio,
  • E ho un negozio di successi che contiene ciò che è stato realizzato.

Un servizio di applicazione elabora una richiesta. Apre una transazione, aggiorna un aggregato e pubblica un evento di dominio. L'evento di dominio viene archiviato nell'archivio eventi con un ID univoco e un timestamp. Quindi, quando la transazione viene eseguita correttamente, l'evento viene inviato in modo asincrono.

Un altro servizio applicativo nello stesso contesto di delimitazione riceve l'evento di dominio pubblicato. Apre una transazione e verifica se esiste un risultato relativo all'evento di dominio nel negozio dei risultati. Se non si riesce a trovare un risultato simile, il servizio applicativo aggiorna un altro aggregato per ottenere una coerenza finale e pubblica un risultato. Questo risultato è memorizzato nel negozio dei risultati, con un riferimento all'evento di dominio che è stato elaborato e con un tipo di risultato, che può semplicemente essere il nome dell'aggregato.

AchievementID | EventID | AchievementType | CompletedOn
--------------|---------|-----------------|------------
     5        |    3    |        A        |  timestamp  <-- first achievement
     6        |    3    |        B        |  timestamp  <-- second achievement

Naturalmente, questo servizio applicativo può anche pubblicare un evento di dominio, ma per semplicità non considererò questo scenario.

Se il micro-servizio si interrompe, gli eventi di dominio che sono stati archiviati negli ultimi xx secondi prima del crash vengono riprodotti. Ogni servizio applicativo interessato a questi eventi di dominio si comporta come se questi eventi fossero appena stati pubblicati. Controllano se esiste un risultato corrispondente nel negozio degli achievement e processano gli eventi del dominio uno per uno se non è possibile trovare risultati.

Posso riutilizzare questa struttura per elaborare anche i messaggi da una coda di messaggi archiviando nell'archivio eventi un evento speciale denominato MessageReceived. Il payload di questo evento contiene l'ID del messaggio ricevuto ma non ancora elaborato. Quando il messaggio viene elaborato, un risultato viene memorizzato nel negozio dei successi. Questo record viene utilizzato per identificare i messaggi già elaborati in caso di arresto anomalo del servizio.

Infine, un servizio di notifica ascolta tutti gli eventi di dominio pubblicati. Apre una transazione, traduce un evento di dominio in un evento di applicazione (integrazione), invia tale evento agli altri contesti limitati e pubblica un risultato. L'ID del messaggio è l'ID dell'evento di dominio, quindi se il micro-servizio si arresta in modo anomalo e gli eventi del dominio vengono riprodotti, i messaggi che vengono inviati di nuovo possono essere identificati come duplicati.

AchievementID | EventID | AchievementType | CompletedOn
--------------|---------|-----------------|------------
     5        |    3    |        A        |  timestamp
     6        |    3    |        B        |  timestamp
     7        |    3    |  Notification   |  timestamp  <-- won't be published again

Gli eventi dell'applicazione (integrazione) non sono memorizzati. Non è necessario renderli persistenti poiché sono calcolati da eventi di dominio che sono già stati archiviati.

Sembra un po 'complesso, ma tutti gli elementi costitutivi di questa soluzione possono essere implementati in uno chassis di micro-servizi e quindi riutilizzati.

    
risposta data 09.10.2018 - 09:35
fonte