Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Idea: event aggregation or projection engine #5

Closed
lanwin opened this Issue Oct 1, 2012 · 5 comments

Comments

Projects
None yet
3 participants

lanwin commented Oct 1, 2012

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.

Collaborator

jamuhl commented Oct 2, 2012

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 commented Oct 9, 2012

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....

Collaborator

jamuhl commented Dec 21, 2012

@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.

Owner

adrai commented Dec 21, 2012

@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...

Collaborator

jamuhl commented Jan 3, 2013

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

@jamuhl jamuhl closed this Apr 24, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment