UNPKG

vulcain-corejs

Version:
226 lines (224 loc) 11.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments)).next()); }); }; const vulcain_configurationsjs_1 = require('vulcain-configurationsjs'); const messageBus_1 = require('./messageBus'); const annotations_1 = require('../di/annotations'); const common_1 = require('./common'); const os = require('os'); const requestContext_1 = require('../servers/requestContext'); const command_1 = require('../commands/command/command'); const eventHandlerFactory_1 = require('./eventHandlerFactory'); const conventions_1 = require('../utils/conventions'); const guid = require('node-uuid'); (function (EventNotificationMode) { EventNotificationMode[EventNotificationMode["always"] = 0] = "always"; EventNotificationMode[EventNotificationMode["successOnly"] = 1] = "successOnly"; EventNotificationMode[EventNotificationMode["never"] = 2] = "never"; })(exports.EventNotificationMode || (exports.EventNotificationMode = {})); var EventNotificationMode = exports.EventNotificationMode; class CommandManager { constructor(container) { this.container = container; this._initialized = false; this._hostname = os.hostname(); this._service = process.env[conventions_1.Conventions.instance.ENV_SERVICE_NAME] + "-" + process.env[conventions_1.Conventions.instance.ENV_SERVICE_VERSION]; if (!this._service) throw new Error("VULCAIN_SERVICE_NAME and VULCAIN_SERVICE_VERSION must be defined."); this.messageBus = new messageBus_1.MessageBus(this); this.subscribeToEvents(); } /** * Get the current domain model * @returns {Domain} */ get domain() { if (!this._domain) { this._domain = this.container.get(annotations_1.DefaultServiceNames.Domain); } return this._domain; } get serviceName() { return this._service; } createResponse(ctx, command, error) { let res = { tenant: ctx.tenant, source: this._hostname, startedAt: command.startedAt, service: command.service, schema: command.schema, inputSchema: command.inputSchema, action: command.action, userContext: command.userContext, domain: command.domain, status: error ? "Error" : command.status, correlationId: command.correlationId, taskId: command.taskId }; if (error) res.error = error; return res; } validateRequestData(info, command) { return __awaiter(this, void 0, void 0, function* () { let errors; let inputSchema = info.metadata.inputSchema; if (inputSchema) { let schema = inputSchema && this.domain.getSchema(inputSchema); if (schema) { command.inputSchema = schema.name; // Custom binding if any command.data = schema && schema.bind(command.data); errors = this.domain.validate(command.data, schema); if (errors && !Array.isArray(errors)) errors = [errors]; } if (!errors || errors.length === 0) { // Search if a method naming validate<schema>[Async] exists let methodName = 'validate' + inputSchema; let altMethodName = methodName + 'Async'; errors = info.handler[methodName] && info.handler[methodName](command.data, command.action); if (!errors) errors = info.handler[altMethodName] && (yield info.handler[altMethodName](command.data, command.action)); if (errors && !Array.isArray(errors)) errors = [errors]; } } return errors; }); } getMetadata(command) { let info = CommandManager.commandHandlersFactory.getInfo(null, command.domain, command.schema, command.action); return info.metadata; } runAsync(command, ctx) { return __awaiter(this, void 0, void 0, function* () { let info = CommandManager.commandHandlersFactory.getInfo(ctx.container, command.domain, command.schema, command.action); let eventMode = info.metadata.eventMode || EventNotificationMode.successOnly; vulcain_configurationsjs_1.System.log.write(ctx, { RunAction: command }); try { let errors = yield this.validateRequestData(info, command); if (errors && errors.length > 0) return this.createResponse(ctx, command, { message: "Validation errors", errors: errors }); command.schema = info.metadata.schema; command.correlationId = ctx.correlationId; command.correlationPath = ctx.correlationPath; command.startedAt = vulcain_configurationsjs_1.System.nowAsString(); command.service = this._service; command.userContext = ctx.user || {}; // Register asynchronous task if (!info.metadata.async) { info.handler.requestContext = ctx; info.handler.command = command; let result = yield info.handler[info.method](command.data); command.status = "Success"; let res = this.createResponse(ctx, command); res.value = common_1.HandlerFactory.obfuscateSensibleData(this.domain, this.container, result); res.completedAt = vulcain_configurationsjs_1.System.nowAsString(); if (eventMode === EventNotificationMode.always || eventMode === EventNotificationMode.successOnly) { this.messageBus.sendEvent(res); } return res; } else { // Pending this.messageBus.pushTask(command); return this.createResponse(ctx, command); } } catch (e) { let error = (e instanceof command_1.CommandRuntimeError) ? e.error : e; return this.createResponse(ctx, command, { message: error.message }); } }); } consumeTaskAsync(command) { return __awaiter(this, void 0, void 0, function* () { let ctx = new requestContext_1.RequestContext(this.container, requestContext_1.Pipeline.HttpRequest); ctx.correlationId = command.correlationId || guid.v4(); ctx.correlationPath = "event-"; vulcain_configurationsjs_1.System.log.write(ctx, { runEvent: command }); let info = CommandManager.commandHandlersFactory.getInfo(ctx.container, command.domain, command.schema, command.action); let eventMode = info.metadata.eventMode || EventNotificationMode.always; let res; try { ctx.user = command.userContext; ctx.tenant = command.userContext.tenant; info.handler.requestContext = ctx; info.handler.command = command; let result = yield info.handler[info.method](command.data); command.status = "Success"; res = this.createResponse(ctx, command); res.value = common_1.HandlerFactory.obfuscateSensibleData(this.domain, this.container, result); res.commandMode = "async"; res.completedAt = vulcain_configurationsjs_1.System.nowAsString(); if (eventMode === EventNotificationMode.always || eventMode === EventNotificationMode.successOnly) { this.messageBus.sendEvent(res); } } catch (e) { let error = (e instanceof command_1.CommandRuntimeError) ? e.error : e; res = this.createResponse(ctx, command, { message: error.message }); res.commandMode = "async"; res.completedAt = vulcain_configurationsjs_1.System.nowAsString(); if (eventMode === EventNotificationMode.always) { this.messageBus.sendEvent(res); } vulcain_configurationsjs_1.System.log.error(ctx, e, `Error when processing async action ${info.handler.name} command : ${command}`); } finally { ctx.dispose(); } }); } subscribeToEvents() { if (!this._initialized) { this._initialized = true; for (let item of CommandManager.eventHandlersFactory.allHandlers()) { this.bindEventHandler(item.metadata); } } } bindEventHandler(metadata) { let events = this.messageBus.getEventsQueue(metadata.subscribeToDomain || this.domain.name); events = events.filter((e) => (metadata.subscribeToSchema === "*" || e.schema === metadata.subscribeToSchema)); if (metadata.filter) events = metadata.filter(events); events.subscribe((evt) => { let handlers = CommandManager.eventHandlersFactory.getFilteredHandlers(evt.domain, evt.schema, evt.action); for (let info of handlers) { let handler; let ctx = new requestContext_1.RequestContext(this.container, requestContext_1.Pipeline.EventNotification); ctx.correlationId = evt.correlationId || guid.v4(); ctx.correlationPath = "-"; try { ctx.user = evt.userContext || {}; handler = ctx.container.resolve(info.handler); handler.requestContext = ctx; handler.event = evt; } catch (e) { vulcain_configurationsjs_1.System.log.error(ctx, e, `Unable to create handler ${info.handler.name}`); } try { handler[info.methodName](evt); } catch (e) { let error = (e instanceof command_1.CommandRuntimeError) ? e.error.toString() : (e.message || e.toString()); vulcain_configurationsjs_1.System.log.error(ctx, e, `Error with event handler ${info.handler.name} event : ${evt}`); } } }); } } CommandManager.commandHandlersFactory = new common_1.HandlerFactory(); CommandManager.eventHandlersFactory = new eventHandlerFactory_1.EventHandlerFactory(); exports.CommandManager = CommandManager; //# sourceMappingURL=actions.js.map