sort-eventstore
Version:
Node-eventstore is a node.js module for multiple databases. It can be very useful as eventstore if you work with (d)ddd, cqrs, eventsourcing, commands and events, etc.
135 lines (112 loc) • 3.47 kB
JavaScript
var debug = require('debug')('eventstore:eventdispatcher');
/**
* Eventstore constructor
* @param {Object} options The options.
* @param publisher the publisher that should be injected
* @param store the store that should be injected
* @constructor
*/
function EventDispatcher(publisher, store) {
this.publisher = publisher;
this.store = store;
this.undispatchedEventsQueue = [];
}
/**
* Triggers to publish all events in undispatchedEventsQueue.
*/
function trigger (dispatcher) {
var queue = dispatcher.undispatchedEventsQueue || []
var event;
// if the last loop is still in progress leave this loop
if (dispatcher.isRunning) return;
dispatcher.isRunning = true;
(function next (e) {
// dipatch one event in queue and call the _next_ callback, which
// will call _process_ for the next undispatched event in queue.
function process (event, nxt) {
// Publish it now...
debug('publish event...');
dispatcher.publisher(event.payload, function(err) {
if (err) {
return debug(err);
}
// ...and set the published event to dispatched.
debug('set event to dispatched...');
dispatcher.store.setEventToDispatched(event, function(err) {
if (err) {
debug(err);
} else {
debug('event set to dispatched');
}
});
});
nxt();
}
// serial process all events in queue
if (!e && queue.length) {
process(queue.shift(), next)
} else {
debug(e);
}
})();
dispatcher.isRunning = false;
}
EventDispatcher.prototype = {
/**
* Queues the passed in events for dispatching.
* @param events
*/
addUndispatchedEvents: function(events) {
var self = this;
events.forEach(function(event) {
self.undispatchedEventsQueue.push(event);
});
trigger(this);
},
/**
* Starts the instance to publish all undispatched events.
* @param callback the function that will be called when this action has finished
*/
start: function(callback) {
if (typeof this.publisher !== 'function') {
var pubErrMsg = 'publisher not injected!';
debug(pubErrMsg);
if (callback) callback(new Error(pubErrMsg));
return;
}
if (!this.store || typeof this.store.getUndispatchedEvents !== 'function'
|| typeof this.store.setEventToDispatched !== 'function') {
var storeErrMsg = 'store not injected!';
debug(storeErrMsg);
if (callback) callback(new Error(storeErrMsg))
return;
}
var self = this;
// Get all undispatched events from store and queue them
// before all other events passed in by the addUndispatchedEvents function.
this.store.getUndispatchedEvents(function(err, events) {
if (err) {
debug(err);
if (callback) callback(err);
return;
}
var triggered = false;
if (events) {
for (var i = 0, len = events.length; i < len; i++) {
self.undispatchedEventsQueue.push(events[i]);
// If there are a lot of events then we can hit issues with the call stack size when processing in one go
triggered = false;
if (i % 1000 === 0){
triggered = true;
trigger(self);
}
}
}
if (!triggered) {
trigger(self);
}
if (callback) callback(null);
});
}
};
module.exports = EventDispatcher;