Quali eventi memorizzare con event-sourcing?

5

Sto pianificando gli eventi che la mia applicazione creerà, ma sto incontrando problemi con il mio progetto. Credo di non applicare correttamente i concetti di event-source.

Prendi l'esempio del conto bancario. La mia applicazione riceve un comando per depositare denaro, accettarlo e quindi creare l'evento CashDeposited . In base alla logica aziendale, il saldo più alto del conto fa innalzare il tasso di interesse, quindi creo l'evento InterestRateChanged .

Ora se registro entrambi questi eventi nel mio archivio eventi, al riavvio, verranno ripetuti entrambi gli eventi. Ma poiché l'evento CashDeposited attiva l'evento InterestRateChanged , il InterestRateChanged non verrà riprodotto due volte: una volta dall'archivio degli eventi e una volta come risultato del fatto che CashDeposited è stata riprodotta?

    
posta user2303 06.02.2015 - 16:57
fonte

3 risposte

4

My application receives a command to deposit cash, accepts it, and then creates the event CashDeposited. Based on the business logic, the higher account balance triggers the interest rate to be increased, so I create the event InterestRateChanged.

Now if I record both of these events to my event store, upon restart, both events will be replayed.

Buona. Questo è esattamente quello che vuoi.

But because the CashDeposited event triggers the InterestRateChanged event, won't the InterestRateChanged be replayed twice: once from the event store and once as a result of CashDeposited being replayed?

Sì, se stai riscontrando questo problema, la tua logica di business potrebbe essere nel posto sbagliato.

Molto ampiamente: la parte gestore di eventi della tua entità dovrebbe essere semplice; applica le modifiche di stato implicite dall'evento, convalida l'invarianza di business e nient'altro .

Gli eventi stessi sono tipicamente creati eseguendo un comando sulla tua entità - è il comando che ha la logica aziendale per dire "aumentare il saldo, e poi se il trigger scatta, allora cambia il tasso di interesse". Nel tuo esempio specifico, quell'unico comando genererà due eventi (perfettamente ragionevoli).

Quando ricarichi l'entità, riproduci gli eventi , ma non i comandi che li hanno prodotti. Quindi la riproduzione include tutte le modifiche allo stato, ma non riesegui la logica aziendale.

    
risposta data 19.01.2016 - 19:25
fonte
3

Raccomando una corretta implementazione del modello di gateway . Come afferma Martin Fowler :

Many of the advantages of Event Sourcing stem from the ability to replay events at will, but if these events cause update messages to be sent to external systems, then things will go wrong because those external systems don't know the difference between real processing and replays.

To handle this you'll need to wrap any external systems with a Gateway. This in itself isn't too onerous since it's a thoroughly good idea in any case. The gateway has to be a bit more sophisticated so it can deal with any replay processing that the Event Sourcing system is doing.

per esempio:.

public class VerySimpleGateway()
{
    public bool IsReplayMode;

    public void FilterProcessingEvent(IEvent event)
    {
        if (IsReplayMode) {
            // for example delete event from event processing queue or adjust event state itself
            // next processing component in the pipeline is informed not to touch this event
        }
    }
}

Nella pipeline di elaborazione degli eventi puoi trattare tale gateway come un passo in schema di responsabilità della catena .

    
risposta data 06.02.2015 - 17:14
fonte
1

Hai due scelte

  • Archivia solo eventi trigger / primi / esterni nell'archivio eventi In questo caso il tuo evento "CashDeposited". Quindi quando ripeti il questo tutti gli eventi successivi verranno attivati come da normale elaborazione.
  • Memorizza tutti gli eventi, ma controlla un flag "isReplay" prima di attivare un evento successivo.

Mi piace la prima opzione migliore. Se si sta riproducendo perché si è verificato un errore (ad esempio si imposta la soglia per un aumento del tasso di interesse troppo basso), il sistema verrà riprodotto correttamente con il parametro fisso. Inoltre, non vuoi davvero complicare il codice e testare con tutti quei percorsi extra per "inReply".

    
risposta data 08.04.2015 - 12:12
fonte

Leggi altre domande sui tag