UNPKG

@atomist/automation-client

Version:
166 lines • 6.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stringify = require("json-stringify-safe"); const ApolloGraphClientFactory_1 = require("../../../graph/ApolloGraphClientFactory"); const AutomationEventListener_1 = require("../../../server/AutomationEventListener"); const MessageClientSupport_1 = require("../../../spi/message/MessageClientSupport"); const Deferred_1 = require("../../util/Deferred"); const logger_1 = require("../../util/logger"); const memory_1 = require("../../util/memory"); const shutdown_1 = require("../../util/shutdown"); const string_1 = require("../../util/string"); const AbstractRequestProcessor_1 = require("../AbstractRequestProcessor"); const messages_1 = require("./messages"); /** * A RequestProcessor that is being run as Node.JS Cluster worker handling all the actual work. */ class ClusterWorkerRequestProcessor extends AbstractRequestProcessor_1.AbstractRequestProcessor { /* tslint:disable:variable-name */ constructor(_automations, _configuration, _listeners = []) { super(_automations, _configuration, [..._listeners, new ClusterWorkerAutomationEventListener()]); this._automations = _automations; this._configuration = _configuration; this._listeners = _listeners; messages_1.workerSend({ type: "online", context: null }); shutdown_1.registerShutdownHook(() => { if (this._configuration.ws && this._configuration.ws.termination && this._configuration.ws.termination.graceful === true) { logger_1.logger.info("Initiating worker shutdown"); // Now wait for configured timeout to let in-flight messages finish processing const deferred = new Deferred_1.Deferred(); setTimeout(() => { logger_1.logger.info("Shutting down worker"); deferred.resolve(0); }, this._configuration.ws.termination.gracePeriod + 2500); return deferred.promise .then(code => { return code; }); } else { logger_1.logger.info("Shutting down worker"); return Promise.resolve(0); } }); } /* tslint:enable:variable-name */ setRegistration(registration) { logger_1.logger.debug("Receiving registration '%s'", stringify(registration)); this.registration = registration; this.graphClients = new ApolloGraphClientFactory_1.ApolloGraphClientFactory(this._configuration, () => `Bearer ${registration.jwt}`); } setRegistrationIfRequired(data) { if (!this.registration) { this.setRegistration(data.registration); } } sendStatusMessage(payload, ctx) { return messages_1.workerSend({ type: "status", context: ctx.context, data: payload, }); } createGraphClient(event, context) { return this.graphClients.createGraphClient(event); } createMessageClient(event, context) { return new ClusterWorkerMessageClient(event, context); } setupNamespace(request, automations, invocationId = string_1.guid(), ts = Date.now()) { const context = request.__context; delete request.__context; return context; } } exports.ClusterWorkerRequestProcessor = ClusterWorkerRequestProcessor; class ClusterWorkerMessageClient extends MessageClientSupport_1.MessageClientSupport { constructor(event, ctx) { super(); this.event = event; this.ctx = ctx; } doSend(msg, destinations, options) { return messages_1.workerSend({ type: "message", context: this.ctx.context, data: { message: msg, destinations, options, }, }); } } class ClusterWorkerAutomationEventListener extends AutomationEventListener_1.AutomationEventListenerSupport { commandSuccessful(payload, ctx, result) { return messages_1.workerSend({ type: "command_success", event: payload, context: ctx.context, data: result, }); } commandFailed(payload, ctx, err) { return messages_1.workerSend({ type: "command_failure", event: payload, context: ctx.context, data: err, }); } eventSuccessful(payload, ctx, result) { return messages_1.workerSend({ type: "event_success", event: payload, context: ctx.context, data: result, }); } eventFailed(payload, ctx, err) { return messages_1.workerSend({ type: "event_failure", event: payload, context: ctx.context, data: err, }); } } /** * Start a new worker node * @param {AutomationServer} automations * @param {WebSocketClientOptions} options * @returns {RequestProcessor} */ function startWorker(automations, configuration, listeners = []) { const worker = new ClusterWorkerRequestProcessor(automations, configuration, listeners); process.on("message", msg => { if (msg.type === "registration") { worker.setRegistration(msg.registration); } else if (msg.type === "command") { worker.setRegistrationIfRequired(msg); worker.processCommand(decorateContext(msg)); } else if (msg.type === "event") { worker.setRegistrationIfRequired(msg); worker.processEvent(decorateContext(msg)); } else if (msg.type === "gc") { memory_1.gc(); } else if (msg.type === "heapdump") { memory_1.heapDump(); } }); return worker; } exports.startWorker = startWorker; function decorateContext(msg) { const event = msg.data; event.__context = msg.context; return event; } //# sourceMappingURL=ClusterWorkerRequestProcessor.js.map