Sono incuriosito dal pattern Sourcing di eventi ma sto cercando di progettare un modello di sourcing di eventi e metterlo in forma concreta .
Prima di tutto, voglio assicurarmi di comprendere i principali casi d'uso di questo modello. Poiché lo capisco , uno utilizza l'individuazione degli eventi per acquisire le modifiche di stato nella tua app in diversi momenti, in modo che tu possa:
- Riproduci gli eventi per riavvolgere l'app in uno stato precedente; o
- Riproduci eventi in un altro ambiente per ricreare la produzione a un certo punto nel tempo e risolverlo
Quindi, prima di tutto, se ho frainteso i principali casi d'uso per l'event sourcing, o se mi mancano quelli principali, per favore cominciamo a correggermi!
Supponendo che io sia più o meno in pista, il mio vero ostacolo mentale sta nel modello di persistenza degli eventi.
- Quanti database ci sono in un sistema di approvvigionamento di eventi? Ci sono due database (uno per la memorizzazione delle entità principali e un altro per la memorizzazione degli eventi)? O c'è solo un database in cui tutte le entità sono gli eventi persistenti stessi?
- Come acquisisci gli eventi (e li proteggi!) per cose che sono totalmente al di fuori del controllo dell'app? Ad esempio: lo stato di alcune API di terze parti con cui la tua app si integra o un broker di messaggi (e lo stato di tutti i suoi messaggi / code) con cui la tua app si integra, argomenti della riga di comando runtime passati nella tua app, ecc.?
- Come funziona il meccanismo di riproduzione attualmente ? Quindi hai alcune entità. Hai eventi che descrivono le modifiche di stato a tali entità. Puoi leggere quegli eventi (e / o le entità che rappresentano) dal database, ma poi hai bisogno di qualcosa per scrivere effettivamente quegli eventi da qualche altra parte. Quindi questo "replayer" tratta solo ogni evento successivo come aggiornamento di un'entità esistente?
Il mio tentativo migliore (finora):
L'entità (i):
// Groovy pseudo-code
class Order {
Long id
Long userId
Long paymentMethodId // Perhaps an ID to a 3rd party system that
// is PCI compliant, etc.
// Constructors, getters/setters, etc.
}
// Each 'Order' has 1+ 'OrderLineItems'
class OrderLineItem {
Long id
Long orderId
Long productId // 'Product' is yet another entity, etc.
Integer quantity
// Constructors, getters/setters, etc.
}
L'evento:
abstract class BaseEvent<ENTITY> {
Date occurredOn
Date recordedOn
ENTITY entity
BaseEvent(ENTITY entity) {
super()
this.occurredOn = new Date() // now
this.entity = entity
}
}
class OrderEvent extends BaseEvent<Order> {
// Perhaps some other metadata about order events
OrderEvent(Order order) {
super(order)
}
}
OK, questo è un buon passo nella giusta direzione, ma ancora non mi aiuta a capire come il "meccanismo di riproduzione" sarà in grado di caricare OrderEvents
da un database, e in realtà "riprodurli" in inserisci un altro database in uno stato particolare che rappresenta un singolo punto nel tempo.