UNPKG

demeine

Version:

DDDD - Distributed Domain Driven Design

173 lines (172 loc) 6.67 kB
"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; }();