Introduktion til CQRS og event sourcing #3

I det forrige indlæg så hvordan vi kunne kode en Beetroot, som vi kunne sende en SqueezeCommand til. Når command’en blev processeret ville den kalde Squeeze(howMuch)-funktionen på rødbeden, som så ville emitte en BeetrootSquashed event hvis den stadig havde list saft i sig, og ellers ville den emitte en BeetrootCompletelyCrushed – så langt så godt!

Men vi mangler stadigvæk at få bragt lidt liv i det hele, og det er det vi skal kigge på i dette indlæg.

Command-processering

Udgangspunktet for alt hvad der sker i et Cirqus-baseret system er, at vi skal have fat i noget, der kan processere vores commands – og det er ikke så svært at få fat i sådan en, for du kan bare gøre sådan her:

var commandProcessor = new CommandProcessor(...);

hvor ... skal udfyldes med 3 afhængigheder:

  • IEventStore: En implementation af noget, der kan gemme og hente events (kan p.t. gøres i SQL Server, MongoDB og PostgreSQL)
  • IAggregateRootRepository: En implementation af noget, der kan hjælpe med at hydrere aggregate roots (findes p.t. kun i en “naiv” variant: En, der laver fuld hydrering hver gang der er behov)
  • IEventDispatcher: En implementation af noget, der gerne vil have mulighed for at arbejde videre på events i takt med at de bliver genereret (f.eks. til views/projektioner, integration til andre systemer, osv.)

Lad os starte med at bruge SQL Server som event store – det kan vi gøre sådan her:

var eventStore = new MsSqlEventStore("mssql", "Events", automaticallyCreateSchema: true);

forudsat at vi har en connection string i vores app.config med navnet “mssql”. Vores aggregate root repository hedder DefaultAggregateRootRepository og kræver et IEventStore for at kunne fungere (fordi den skal hydrere aggregate roots på baggrund af events):

var aggregateRootRepository = new DefaultAggregateRootRepository(eventStore);

Afslutningsvis skal vi stille med en IEventDispatcher, og der tager vi fat i en, der senere kan benyttes til at generere view-delen af vores system – den kræver et aggregate root repository fordi views skal kunne loade aggregate roots hvis de har brug for det:

var eventDispatcher = new ViewManagerEventDispatcher(aggregateRootRepository);

Hvis man sætter det sammen, så ser det således ud:

// ved opstart:
var eventStore = new MsSqlEventStore("mssql", "Events", automaticallyCreateSchema: true);
var repository = new DefaultAggregateRootRepository(eventStore);
var dispatcher = new ViewManagerEventDispatcher(aggregateRootRepository);

var commandProcessor = new CommandProcessor(eventStore, repository, dispatcher);

// først....
commandProcessor.Initialize();

// og så i resten af applikationens levetid:
commandProcessor.ProcessCommand(...);

og det er faktisk alt, hvad der skal til for at kunne komme i gang med at kode en rig domænemodel baseret på event sourcing – ikke så ringe, hvis du spørger mig 🙂

I næste indlæg vil vi kigge på hvordan man kan etablere en projektion af vores events: Et view, som holdes opdateret med events efterhånden som de bliver genereret. Stay tuned….

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *