Event-Driven Architecture: eventi di dominio senza rendere tutto asincrono
L'Event-Driven Architecture disaccoppia bounded context attraverso fatti di dominio, ma richiede una scelta consapevole tra sincrono e asincrono.
Evento significa fatto, non comando mascherato
Un Domain Event descrive qualcosa che è già accaduto nel dominio: PatientAdmitted, PatientTransferred, OrderPlaced, ResultAvailable, DocumentSigned. Il producer non dice ai consumer cosa devono fare; pubblica un fatto con un significato stabile.
Quando usare comunicazione asincrona
Più bounded context devono reagire allo stesso fatto.
Il producer non deve attendere il completamento di tutti i consumer.
È accettabile una breve eventual consistency.
Si vuole ridurre l'accoppiamento temporale: un consumer può essere momentaneamente indisponibile.
Quando preferire il sincrono
L'utente ha bisogno della risposta per proseguire il caso d'uso.
Serve validare una precondizione prima di confermare il comando.
La consistenza deve essere immediata nel confine transazionale.
Una semplice query al proprietario del dato è più chiara di un meccanismo di replica.
Esempio
ADT conferma un ricovero nella propria transazione. Dopo il commit pubblica PatientAdmitted. Bed Management prepara l'occupazione, Clinical Record inizializza il contesto di reparto e Notification valuta eventuali comunicazioni. ADT non deve chiamare in sequenza tre API e restare bloccato dal servizio meno disponibile.
Contratto dell'evento
Un evento deve avere identificatore, tipo/versione, aggregateId, timestamp, correlationId e payload minimo sufficiente. Evitare di copiare nell'evento l'intero documento paziente solo per comodità: ogni campo duplicato aumenta accoppiamento e rischi di privacy.
Eventual consistency non significa incoerenza incontrollata
Il sistema deve rendere osservabili ritardi, retry, dead letter e lag dei consumer. Le UI possono mostrare stati intermedi espliciti. Per processi che attraversano più contesti e richiedono compensazioni, può essere opportuno un Process Manager/Saga.
Errore frequente
Sostituire ogni HTTP con RabbitMQ non crea un'architettura migliore: sposta soltanto l'accoppiamento dentro messaggi più difficili da tracciare.
Il complemento necessario
Se l'evento nasce dalla stessa modifica salvata nel database, il Transactional Outbox evita il dual write tra commit DB e publish sul broker.
