@atomist/automation-client
Version:
Atomist API for software low-level client
225 lines • 10.9 kB
JavaScript
"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