1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const cluster = require("cluster");
|
4 | const stringify = require("json-stringify-safe");
|
5 | const applicationEvent_1 = require("./internal/env/applicationEvent");
|
6 | const ClusterMasterRequestProcessor_1 = require("./internal/transport/cluster/ClusterMasterRequestProcessor");
|
7 | const ClusterWorkerRequestProcessor_1 = require("./internal/transport/cluster/ClusterWorkerRequestProcessor");
|
8 | const EventStoringAutomationEventListener_1 = require("./internal/transport/EventStoringAutomationEventListener");
|
9 | const ExpressRequestProcessor_1 = require("./internal/transport/express/ExpressRequestProcessor");
|
10 | const ExpressServer_1 = require("./internal/transport/express/ExpressServer");
|
11 | const MetricEnabledAutomationEventListener_1 = require("./internal/transport/MetricEnabledAutomationEventListener");
|
12 | const showStartupMessages_1 = require("./internal/transport/showStartupMessages");
|
13 | const DefaultWebSocketRequestProcessor_1 = require("./internal/transport/websocket/DefaultWebSocketRequestProcessor");
|
14 | const payloads_1 = require("./internal/transport/websocket/payloads");
|
15 | const WebSocketClient_1 = require("./internal/transport/websocket/WebSocketClient");
|
16 | const shutdown_1 = require("./internal/util/shutdown");
|
17 | const string_1 = require("./internal/util/string");
|
18 | const BuildableAutomationServer_1 = require("./server/BuildableAutomationServer");
|
19 | const statsd_1 = require("./spi/statsd/statsd");
|
20 | const logger_1 = require("./util/logger");
|
21 | const redact_1 = require("./util/redact");
|
22 | class AutomationClient {
|
23 | constructor(configuration) {
|
24 | this.configuration = configuration;
|
25 | this.defaultListeners = [
|
26 | new MetricEnabledAutomationEventListener_1.MetricEnabledAutomationEventListener(),
|
27 | new EventStoringAutomationEventListener_1.EventStoringAutomationEventListener(),
|
28 | new showStartupMessages_1.StartupMessageAutomationEventListener(),
|
29 | new showStartupMessages_1.StartupTimeMessageUatomationEventListener(),
|
30 | ];
|
31 | this.automations = new BuildableAutomationServer_1.BuildableAutomationServer(configuration);
|
32 | global.__runningAutomationClient = this;
|
33 | }
|
34 | get automationServer() {
|
35 | return this.automations;
|
36 | }
|
37 | withCommandHandler(chm) {
|
38 | this.automations.registerCommandHandler(chm);
|
39 | return this;
|
40 | }
|
41 | withEventHandler(event) {
|
42 | this.automations.registerEventHandler(event);
|
43 | return this;
|
44 | }
|
45 | withIngester(ingester) {
|
46 | this.automations.registerIngester(ingester);
|
47 | return this;
|
48 | }
|
49 | processCommand(command, callback) {
|
50 | if (this.webSocketHandler) {
|
51 | return this.webSocketHandler.processCommand(command, callback);
|
52 | }
|
53 | else if (this.httpHandler) {
|
54 | return this.httpHandler.processCommand(command, callback);
|
55 | }
|
56 | else {
|
57 | throw new Error("No request processor available");
|
58 | }
|
59 | }
|
60 | processEvent(event, callback) {
|
61 | if (this.webSocketHandler) {
|
62 | return this.webSocketHandler.processEvent(event, callback);
|
63 | }
|
64 | else if (this.httpHandler) {
|
65 | return this.httpHandler.processEvent(event, callback);
|
66 | }
|
67 | else {
|
68 | throw new Error("No request processor available");
|
69 | }
|
70 | }
|
71 | run() {
|
72 | this.configureRedactions();
|
73 | logger_1.configureLogging(logger_1.clientLoggingConfiguration(this.configuration));
|
74 | this.configureShutdown();
|
75 | this.configureStatsd();
|
76 | const clientSig = `${this.configuration.name}:${this.configuration.version}`;
|
77 | const clientConf = stringify(this.configuration, string_1.obfuscateJson);
|
78 | if (!this.configuration.cluster.enabled) {
|
79 | logger_1.logger.info(`Starting Atomist automation client ${clientSig}`);
|
80 | logger_1.logger.debug(`Using automation client configuration: ${clientConf}`);
|
81 | if (this.configuration.ws.enabled) {
|
82 | return Promise.all([
|
83 | this.runWs(() => this.setupWebSocketRequestHandler()),
|
84 | this.runHttp(() => this.setupExpressRequestHandler()),
|
85 | ])
|
86 | .then(() => this.setupApplicationEvents())
|
87 | .then(() => this.raiseStartupEvent());
|
88 | }
|
89 | else {
|
90 | return this.runHttp(() => this.setupExpressRequestHandler())
|
91 | .then(() => this.setupApplicationEvents())
|
92 | .then(() => this.raiseStartupEvent());
|
93 | }
|
94 | }
|
95 | else if (cluster.isMaster) {
|
96 | logger_1.logger.info(`Starting Atomist automation client master ${clientSig}`);
|
97 | logger_1.logger.debug(`Using automation client configuration: ${clientConf}`);
|
98 | this.webSocketHandler = this.setupWebSocketClusterRequestHandler();
|
99 | return this.webSocketHandler.run()
|
100 | .then(() => {
|
101 | return Promise.all([
|
102 | this.runWs(() => this.webSocketHandler),
|
103 | this.runHttp(() => this.setupExpressRequestHandler()),
|
104 | ])
|
105 | .then(() => this.setupApplicationEvents())
|
106 | .then(() => this.raiseStartupEvent());
|
107 | });
|
108 | }
|
109 | else if (cluster.isWorker) {
|
110 | logger_1.logger.info(`Starting Atomist automation client worker ${clientSig}`);
|
111 | return Promise.resolve(this.setupWebSocketClusterWorkerRequestHandler())
|
112 | .then(workerProcessor => {
|
113 | this.webSocketHandler = workerProcessor;
|
114 | return this.raiseStartupEvent();
|
115 | });
|
116 | }
|
117 | }
|
118 | configureRedactions() {
|
119 | if (!!this.configuration.redact && !!this.configuration.redact.patterns) {
|
120 | this.configuration.redact.patterns.forEach(p => {
|
121 | let regexp;
|
122 | if (typeof p.regexp === "string") {
|
123 | regexp = new RegExp(p.regexp, "g");
|
124 | }
|
125 | else {
|
126 | regexp = p.regexp;
|
127 | }
|
128 | redact_1.addRedaction(regexp, p.replacement);
|
129 | });
|
130 | }
|
131 | }
|
132 | raiseStartupEvent() {
|
133 | return [...this.defaultListeners, ...this.configuration.listeners].filter(l => l.startupSuccessful)
|
134 | .map(l => () => l.startupSuccessful(this))
|
135 | .reduce((p, f) => p.then(f), Promise.resolve());
|
136 | }
|
137 | configureShutdown() {
|
138 | const gracePeriod = shutdown_1.terminationGracePeriod(this.configuration);
|
139 | shutdown_1.setForceExitTimeout(gracePeriod * 10);
|
140 | }
|
141 | configureStatsd() {
|
142 | if (this.configuration.statsd.enabled === true) {
|
143 | this.defaultListeners.push(new statsd_1.StatsdAutomationEventListener(this.configuration));
|
144 | }
|
145 | }
|
146 | setupWebSocketClusterRequestHandler() {
|
147 | return new ClusterMasterRequestProcessor_1.ClusterMasterRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners], this.configuration.cluster.workers, this.configuration.cluster.maxConcurrentPerWorker);
|
148 | }
|
149 | setupWebSocketClusterWorkerRequestHandler() {
|
150 | return ClusterWorkerRequestProcessor_1.startWorker(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]);
|
151 | }
|
152 | setupWebSocketRequestHandler() {
|
153 | return new DefaultWebSocketRequestProcessor_1.DefaultWebSocketRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]);
|
154 | }
|
155 | setupApplicationEvents() {
|
156 | if (this.configuration.applicationEvents.enabled) {
|
157 | if (this.configuration.applicationEvents.workspaceId) {
|
158 | return applicationEvent_1.registerApplicationEvents(this.configuration.applicationEvents.workspaceId, this.configuration);
|
159 | }
|
160 | else if (this.configuration.workspaceIds.length > 0) {
|
161 | return applicationEvent_1.registerApplicationEvents(this.configuration.workspaceIds[0], this.configuration);
|
162 | }
|
163 | }
|
164 | return Promise.resolve();
|
165 | }
|
166 | setupExpressRequestHandler() {
|
167 | return new ExpressRequestProcessor_1.ExpressRequestProcessor(this.automations, this.configuration, [...this.defaultListeners, ...this.configuration.listeners]);
|
168 | }
|
169 | runWs(handlerMaker) {
|
170 | const payloadOptions = {};
|
171 | if (this.configuration.ws && this.configuration.ws.compress) {
|
172 | payloadOptions.accept_encoding = "gzip";
|
173 | }
|
174 | this.webSocketHandler = handlerMaker();
|
175 | this.webSocketClient = new WebSocketClient_1.WebSocketClient(() => payloads_1.prepareRegistration(this.automations.automations, payloadOptions, this.configuration.metadata), this.configuration, this.webSocketHandler);
|
176 | return this.webSocketClient.start();
|
177 | }
|
178 | runHttp(handlerMaker) {
|
179 | if (!this.configuration.http.enabled) {
|
180 | return;
|
181 | }
|
182 | this.httpHandler = handlerMaker();
|
183 | this.httpServer = new ExpressServer_1.ExpressServer(this.automations, this.configuration, this.httpHandler);
|
184 | return this.httpServer.run();
|
185 | }
|
186 | }
|
187 | exports.AutomationClient = AutomationClient;
|
188 | function automationClient(configuration) {
|
189 | const client = new AutomationClient(configuration);
|
190 | configuration.commands.forEach(c => {
|
191 | client.withCommandHandler(c);
|
192 | });
|
193 | configuration.events.forEach(e => {
|
194 | client.withEventHandler(e);
|
195 | });
|
196 | configuration.ingesters.forEach(e => {
|
197 | client.withIngester(e);
|
198 | });
|
199 | return client;
|
200 | }
|
201 | exports.automationClient = automationClient;
|
202 |
|
\ | No newline at end of file |