demeine
Version:
DDDD - Distributed Domain Driven Design
173 lines (172 loc) • 6.67 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Aggregate", {
enumerable: true,
get: function() {
return Aggregate;
}
});
var _errorUtils = require("../utils/errorUtils");
var _queue = require("../queue/Queue");
var _bluebird = /*#__PURE__*/ _interopRequireDefault(require("bluebird"));
var _slf = require("slf");
var _uuid = require("uuid");
var _defaultEventHandler = require("./DefaultEventHandler");
var _defaultCommandHandler = require("./DefaultCommandHandler");
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
var LOG = _slf.LoggerFactory.getLogger("demeine:aggregate");
function _promise(result, warning) {
if (!(result === null || result === void 0 ? void 0 : result.then)) {
LOG.warn(warning || "not returning promise as expected");
return _bluebird.default.resolve(true);
}
return result;
}
var Aggregate = /*#__PURE__*/ function() {
"use strict";
function Aggregate(commandSink, eventHandler, commandHandler) {
var _this = this;
_classCallCheck(this, Aggregate);
this._uncommittedEvents = [];
this._commandSink = commandSink || {
sink: function(cmd) {
return _this._process(cmd);
}
};
this._eventHandler = eventHandler || new _defaultEventHandler.DefaultEventHandler();
this._commandHandler = commandHandler || new _defaultCommandHandler.DefaultCommandHandler();
this._version = 0;
this._commandQueue = new _queue.Queue();
this._state = {};
this.id = (0, _uuid.v4)();
}
var _proto = Aggregate.prototype;
_proto._rehydrate = function _rehydrate(events, version, snapshot) {
LOG.info("rehydrating aggregate with %d events to version %d has snapshot %s", events.length, version, snapshot !== undefined);
// do another way?
if (snapshot) {
this._state = snapshot;
}
for(var i = 0; i < events.length; i++){
this._apply(events[i], false);
}
this._version = version || this._version;
};
_proto._getSnapshot = function _getSnapshot() {
return this._state;
};
_proto._apply = function _apply(event, isNew) {
LOG.debug("applying event %j %s", event, isNew);
if (!event.id) {
event.id = (0, _uuid.v4)();
}
if (!event.type || !event.aggregateId || event.aggregateId != this.id) {
throw new Error("event is missing data: ".concat(JSON.stringify(event)));
}
this._eventHandler.handle(this, event);
if (this._version == -1) {
this._version = 0;
}
this._version++;
if (isNew) {
this._uncommittedEvents.push(event);
}
return this;
};
_proto._process = function _process(command) {
var _this = this;
LOG.info("processing command %j", command);
return new _bluebird.default(function(resolve, reject) {
try {
var handler = _this._commandHandler.handle(_this, command);
resolve(handler);
} catch (error) {
reject(error);
}
}).error(function(error) {
LOG.error("Failed to process command %j. Error: %s", command, (0, _errorUtils.getMessageFromError)(error));
_this.clearUncommittedEvents();
throw error;
});
};
_proto._sink = function _sink(commandToSink) {
var _this = this;
LOG.info("sinking command %j", commandToSink);
return this._commandQueue.queueCommand(function() {
var resolvedCommand = _bluebird.default.resolve(commandToSink);
var aggregatePromise = resolvedCommand.then(function(command) {
if (!command.id) {
LOG.warn("No command id set, setting it automatiically");
command.id = (0, _uuid.v4)();
}
if (!command.type || !command.aggregateId || command.aggregateId !== _this.id) {
var error = new Error("command is missing data: ".concat(JSON.stringify(command)));
LOG.error("Unable to sink command. Error: %s", (0, _errorUtils.getMessageFromError)(error));
throw error;
}
if (_this.type) {
command.aggregateType = _this.type;
}
var aggregate = _this._commandSink.sink(command, _this);
return _promise(aggregate, "sinking command but not returning promise, commands status and chaining might not work as expected");
});
return aggregatePromise;
});
};
/**
* Built in functionality to manage deletion of Aggregates / streams
*/ _proto.delete = function _delete() {
return this._sink({
type: "$stream.delete.command",
aggregateId: this.id,
payload: {}
});
};
_proto.processDelete = function processDelete(command) {
return this._apply({
type: "$stream.deleted.event",
aggregateId: this.id,
correlationId: command.id,
payload: {
aggregateType: this.type
}
}, true);
};
_proto.applyDeleted = function applyDeleted() {};
_proto.getVersion = function getVersion() {
return this._version;
};
_proto.getUncommittedEvents = function getUncommittedEvents() {
//throw if async cmd is on queue
if (this._commandQueue.isProcessing()) {
throw new Error("Cannot get uncommitted events while there is still commands in queue - try using getUncommittedEventsAsync()");
}
return this._uncommittedEvents;
};
_proto.getUncommittedEventsAsync = function getUncommittedEventsAsync() {
var _this = this;
return this._commandQueue.empty().then(function() {
if (_this._commandQueue.isProcessing()) {
return _this.getUncommittedEventsAsync();
} else {
return _this.getUncommittedEvents();
}
});
};
_proto.clearUncommittedEvents = function clearUncommittedEvents() {
LOG.info("Clearing uncommitted events");
return this._uncommittedEvents = [];
};
return Aggregate;
}();