UNPKG

@atomist/automation-client

Version:

Atomist API for software low-level client

225 lines • 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cluster = require("cluster"); const stringify = require("json-stringify-safe"); const applicationEvent_1 = require("./internal/env/applicationEvent"); const ClusterMasterRequestProcessor_1 = require("./internal/transport/cluster/ClusterMasterRequestProcessor"); const ClusterWorkerRequestProcessor_1 = require("./internal/transport/cluster/ClusterWorkerRequestProcessor"); const EventStoringAutomationEventListener_1 = require("./internal/transport/EventStoringAutomationEventListener"); const ExpressRequestProcessor_1 = require("./internal/transport/express/ExpressRequestProcessor"); const ExpressServer_1 = require("./internal/transport/express/ExpressServer"); const MetricEnabledAutomationEventListener_1 = require("./internal/transport/MetricEnabledAutomationEventListener"); const showStartupMessages_1 = require("./internal/transport/showStartupMessages"); const DefaultWebSocketRequestProcessor_1 = require("./internal/transport/websocket/DefaultWebSocketRequestProcessor"); const payloads_1 = require("./internal/transport/websocket/payloads"); const WebSocketClient_1 = require("./internal/transport/websocket/WebSocketClient"); const shutdown_1 = require("./internal/util/shutdown"); const string_1 = require("./internal/util/string"); const BuildableAutomationServer_1 = require("./server/BuildableAutomationServer"); const statsd_1 = require("./spi/statsd/statsd"); const logger_1 = require("./util/logger"); const redact_1 = require("./util/redact"); const os = require("os"); class AutomationClient { constructor(configuration, requestProcessorMaker) { this.configuration = configuration; this.requestProcessorMaker = requestProcessorMaker; this.defaultListeners = [ new MetricEnabledAutomationEventListener_1.MetricEnabledAutomationEventListener(), new EventStoringAutomationEventListener_1.EventStoringAutomationEventListener(), new showStartupMessages_1.StartupMessageAutomationEventListener(), new showStartupMessages_1.StartupTimeMessageUatomationEventListener(), ]; this.automations = new BuildableAutomationServer_1.BuildableAutomationServer(configuration); global.__runningAutomationClient = this; } get automationServer() { return this.automations; } withCommandHandler(chm) { this.automations.registerCommandHandler(chm); return this; } withEventHandler(event) { this.automations.registerEventHandler(event); return this; } withIngester(ingester) { this.automations.registerIngester(ingester); return this; } processCommand(command, callback) { if (this.requestProcessor) { return this.requestProcessor.processCommand(command, callback); } else if (this.webSocketHandler) { return this.webSocketHandler.processCommand(command, callback); } else if (this.httpHandler) { return this.httpHandler.processCommand(command, callback); } else { throw new Error("No request processor available"); } } processEvent(event, callback) { if (this.requestProcessor) { return this.requestProcessor.processEvent(event, callback); } else if (this.webSocketHandler) { return this.webSocketHandler.processEvent(event, callback); } else if (this.httpHandler) { return this.httpHandler.processEvent(event, callback); } else { throw new Error("No request processor available"); } } run() { this.configureRedactions(); logger_1.configureLogging(logger_1.clientLoggingConfiguration(this.configuration)); this.configureShutdown(); this.configureStatsd(); const clientSig = `${this.configuration.name}:${this.configuration.version}`; const clientConf = stringify(this.configuration, string_1.obfuscateJson); if (!!this.requestProcessorMaker) { this.requestProcessor = this.requestProcessorMaker(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]); } if (!this.configuration.cluster.enabled) { logger_1.logger.info(`Starting Atomist automation client ${clientSig}`); logger_1.logger.debug(`Using automation client configuration: ${clientConf}`); if (this.configuration.ws.enabled) { return Promise.all([ this.runWs(() => this.setupWebSocketRequestHandler()), this.runHttp(() => this.setupExpressRequestHandler()), ]) .then(() => this.setupApplicationEvents()) .then(() => this.raiseStartupEvent()); } else { return this.runHttp(() => this.setupExpressRequestHandler()) .then(() => this.setupApplicationEvents()) .then(() => this.raiseStartupEvent()); } } else if (cluster.isMaster) { logger_1.logger.info(`Starting Atomist automation client master ${clientSig}`); logger_1.logger.debug(`Using automation client configuration: ${clientConf}`); this.webSocketHandler = this.setupWebSocketClusterRequestHandler(); return this.webSocketHandler.run() .then(() => { return Promise.all([ this.runWs(() => this.webSocketHandler), this.runHttp(() => this.setupExpressRequestHandler()), ]) .then(() => this.setupApplicationEvents()) .then(() => this.raiseStartupEvent()); }); } else if (cluster.isWorker) { logger_1.logger.info(`Starting Atomist automation client worker ${clientSig}`); return Promise.resolve(this.setupWebSocketClusterWorkerRequestHandler()) .then(workerProcessor => { this.webSocketHandler = workerProcessor; return this.raiseStartupEvent(); }); } } configureRedactions() { if (!!this.configuration.redact && !!this.configuration.redact.patterns) { this.configuration.redact.patterns.forEach(p => { let regexp; if (typeof p.regexp === "string") { regexp = new RegExp(p.regexp, "g"); } else { regexp = p.regexp; } redact_1.addRedaction(regexp, p.replacement); }); } } raiseStartupEvent() { return [...this.defaultListeners, ...this.configuration.listeners].filter(l => l.startupSuccessful) .map(l => () => l.startupSuccessful(this)) .reduce((p, f) => p.then(f), Promise.resolve()); } configureShutdown() { const gracePeriod = shutdown_1.terminationGracePeriod(this.configuration); shutdown_1.setForceExitTimeout(gracePeriod * 10); } configureStatsd() { if (this.configuration.statsd.enabled === true) { this.defaultListeners.push(new statsd_1.StatsdAutomationEventListener(this.configuration)); } } setupWebSocketClusterRequestHandler() { return new ClusterMasterRequestProcessor_1.ClusterMasterRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners], this.configuration.cluster.workers, this.configuration.cluster.maxConcurrentPerWorker); } setupWebSocketClusterWorkerRequestHandler() { return ClusterWorkerRequestProcessor_1.startWorker(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]); } setupWebSocketRequestHandler() { return new DefaultWebSocketRequestProcessor_1.DefaultWebSocketRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]); } setupApplicationEvents() { if (this.configuration.applicationEvents.enabled) { if (this.configuration.applicationEvents.workspaceId) { return applicationEvent_1.registerApplicationEvents(this.configuration.applicationEvents.workspaceId, this.configuration); } else if (this.configuration.workspaceIds.length > 0) { return applicationEvent_1.registerApplicationEvents(this.configuration.workspaceIds[0], this.configuration); } } return Promise.resolve(); } setupExpressRequestHandler() { return new ExpressRequestProcessor_1.ExpressRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]); } runWs(handlerMaker) { const payloadOptions = {}; if (this.configuration.ws && this.configuration.ws.compress) { payloadOptions.accept_encoding = "gzip"; } this.webSocketHandler = handlerMaker(); this.webSocketClient = new WebSocketClient_1.WebSocketClient(() => payloads_1.prepareRegistration(this.automations.automations, payloadOptions, this.configuration.metadata), this.configuration, this.webSocketHandler); return this.webSocketClient.start(); } runHttp(handlerMaker) { if (!this.configuration.http.enabled) { return Promise.resolve(); } if (this.configuration.http.cluster.enabled && cluster.isMaster) { for (let i = 0; i < (this.configuration.http.cluster.workers || os.cpus().length); i++) { cluster.fork(); } cluster.on("disconnect", worker => { logger_1.logger.warn(`Worker '${worker.id}' disconnected`); }); cluster.on("online", worker => { logger_1.logger.debug(`Worker '${worker.id}' connected`); }); return Promise.resolve(); } this.httpHandler = handlerMaker(); this.httpServer = new ExpressServer_1.ExpressServer(this.automations, this.configuration, this.httpHandler); return this.httpServer.run(); } } exports.AutomationClient = AutomationClient; function automationClient(configuration, requestProcessorMaker) { const client = new AutomationClient(configuration, requestProcessorMaker); configuration.commands.forEach(c => { client.withCommandHandler(c); }); configuration.events.forEach(e => { client.withEventHandler(e); }); configuration.ingesters.forEach(e => { client.withIngester(e); }); return client; } exports.automationClient = automationClient; //# sourceMappingURL=automationClient.js.map