Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Idea: event aggregation or projection engine #5

Closed
lanwin opened this Issue · 5 comments

3 participants

@lanwin

Whats currently missing is a way of aggregating events and projecting them in a simple manner.

Look at the following pseudo code:

var ag = eventstore.createAggregator("uniqueaggregatorname");

ag.on('event',function(e,done){
    // do event projection here 

    // needs to be called to ensure event was processed.
    done(); 
});

ag.start();

What this dose is to call each event only once per unique aggregator name even if the app is restarted. The current cursor should be automatically saved in the underlying event store storage.

If you think future, this can be extended to a full projection engine like this pseudo code:

var pr = eventstore.createProjection("uniqueprojectionname");

pr.state = {name:"-"};

pr.on('project',function(event,state,done){
    if(event.name=="namechanged"){
        state.name = event.name;
    }
    done();
});

pr.on('stateChanged',function(state){
    console.log(state);
});

pr.start();

The difference is that here we store not only the current cursor, but rather the last projected state too.

Currently this is only an idea to inspire a discussion.

@jamuhl
Collaborator

Not to sure what you want to achieve. But generally working on aggregates (commandHandler in domain) or on readmodels (eventdenormalizers) is not concern of the eventstore.

Sample:
commandHandler: https://github.com/jamuhl/nodeCQRS/blob/master/domain/app/commandHandler.js (line 118)
eventDenormalizer: https://github.com/jamuhl/nodeCQRS/blob/master/host/app/eventDenormalizer.js

Modules:
Domain: https://github.com/adrai/node-cqrs-domain
EventDenormalizer: https://github.com/adrai/node-cqrs-eventdenormalizer

@lanwin

Ok forget about the projection thing, that was to far away. The reason for my the aggregator is the following.

It seems the current event dispatcher has some drawbacks.

  1. There is currently now way of replaying all events from begin to recreate the read model.

  2. The publisher.publish will loose events.

publish = function(event){
  database.save(event, function(err){
     //When we are here, the event is already set as dispatched. 
     //If the process crashes or the database returns an error, the
     //event get lost.
  });
}
  1. What if we want more then one publisher and two are succeed and one fails

This is where an Aggregator can help. It replays all events from begin to end. Then it saves the last event id (as a cursor) to the eventstore.storage based on the name (so it can give more then one cursor). On the next run, which can be on interval or triggered by the current publisher, it starts at the last event id and runs to the new end....

@jamuhl
Collaborator

@adrai what do you think?

do we need some callback in the publisher.publish(event, cb) ?

would be safer to set dispatched if publisher really done it.

@adrai
Owner

@jamuhl I think it should stay in the messaging way... like an eventemitter... emit() without callback, otherway this would mean that the evented cqrs-domain module have to change the emitting event too...
Let's discuss this personally...

@jamuhl
Collaborator

@adrai let's discuss this with the other issue on monday in office.

@jamuhl jamuhl closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.