@kapeta/local-cluster-service 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +17 -0
- package/.github/workflows/main.yml +22 -22
- package/.prettierignore +4 -0
- package/.vscode/launch.json +2 -4
- package/CHANGELOG.md +14 -0
- package/definitions.d.ts +17 -35
- package/dist/cjs/index.d.ts +27 -0
- package/dist/cjs/index.js +126 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/assetManager.d.ts +31 -0
- package/dist/cjs/src/assetManager.js +153 -0
- package/dist/cjs/src/assets/routes.d.ts +3 -0
- package/dist/cjs/src/assets/routes.js +117 -0
- package/dist/cjs/src/clusterService.d.ts +40 -0
- package/dist/cjs/src/clusterService.js +114 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +8 -0
- package/dist/cjs/src/codeGeneratorManager.js +53 -0
- package/dist/cjs/src/config/routes.d.ts +3 -0
- package/dist/cjs/src/config/routes.js +126 -0
- package/dist/cjs/src/configManager.d.ts +36 -0
- package/dist/cjs/src/configManager.js +110 -0
- package/dist/cjs/src/containerManager.d.ts +89 -0
- package/dist/cjs/src/containerManager.js +365 -0
- package/dist/cjs/src/filesystem/routes.d.ts +3 -0
- package/dist/cjs/src/filesystem/routes.js +69 -0
- package/dist/cjs/src/filesystemManager.d.ts +15 -0
- package/dist/cjs/src/filesystemManager.js +87 -0
- package/dist/cjs/src/identities/routes.d.ts +3 -0
- package/dist/cjs/src/identities/routes.js +18 -0
- package/dist/cjs/src/instanceManager.d.ts +56 -0
- package/dist/cjs/src/instanceManager.js +424 -0
- package/dist/cjs/src/instances/routes.d.ts +3 -0
- package/dist/cjs/src/instances/routes.js +134 -0
- package/dist/cjs/src/middleware/cors.d.ts +2 -0
- package/dist/cjs/src/middleware/cors.js +10 -0
- package/dist/cjs/src/middleware/kapeta.d.ts +11 -0
- package/dist/cjs/src/middleware/kapeta.js +17 -0
- package/dist/cjs/src/middleware/stringBody.d.ts +5 -0
- package/dist/cjs/src/middleware/stringBody.js +14 -0
- package/dist/cjs/src/networkManager.d.ts +32 -0
- package/dist/cjs/src/networkManager.js +109 -0
- package/dist/cjs/src/operatorManager.d.ts +36 -0
- package/dist/cjs/src/operatorManager.js +165 -0
- package/dist/cjs/src/progressListener.d.ts +20 -0
- package/dist/cjs/src/progressListener.js +91 -0
- package/dist/cjs/src/providerManager.d.ts +9 -0
- package/dist/cjs/src/providerManager.js +51 -0
- package/dist/cjs/src/providers/routes.d.ts +3 -0
- package/dist/cjs/src/providers/routes.js +42 -0
- package/dist/cjs/src/proxy/routes.d.ts +3 -0
- package/dist/cjs/src/proxy/routes.js +111 -0
- package/dist/cjs/src/proxy/types/rest.d.ts +4 -0
- package/dist/cjs/src/proxy/types/rest.js +114 -0
- package/dist/cjs/src/proxy/types/web.d.ts +4 -0
- package/dist/cjs/src/proxy/types/web.js +53 -0
- package/dist/cjs/src/repositoryManager.d.ts +17 -0
- package/dist/cjs/src/repositoryManager.js +218 -0
- package/dist/cjs/src/serviceManager.d.ts +29 -0
- package/dist/cjs/src/serviceManager.js +99 -0
- package/dist/cjs/src/socketManager.d.ts +14 -0
- package/dist/cjs/src/socketManager.js +53 -0
- package/dist/cjs/src/storageService.d.ts +17 -0
- package/dist/cjs/src/storageService.js +74 -0
- package/dist/cjs/src/traffic/routes.d.ts +3 -0
- package/dist/cjs/src/traffic/routes.js +18 -0
- package/dist/cjs/src/types.d.ts +88 -0
- package/dist/cjs/src/types.js +2 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +468 -0
- package/dist/cjs/src/utils/LogData.d.ts +19 -0
- package/dist/cjs/src/utils/LogData.js +43 -0
- package/dist/cjs/src/utils/pathTemplateParser.d.ts +26 -0
- package/dist/cjs/src/utils/pathTemplateParser.js +121 -0
- package/dist/cjs/src/utils/utils.d.ts +1 -0
- package/dist/cjs/src/utils/utils.js +18 -0
- package/dist/cjs/start.d.ts +1 -0
- package/dist/cjs/start.js +12 -0
- package/dist/esm/index.d.ts +27 -0
- package/dist/esm/index.js +121 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/assetManager.d.ts +31 -0
- package/{src → dist/esm/src}/assetManager.js +22 -60
- package/dist/esm/src/assets/routes.d.ts +3 -0
- package/{src → dist/esm/src}/assets/routes.js +21 -36
- package/dist/esm/src/clusterService.d.ts +40 -0
- package/{src → dist/esm/src}/clusterService.js +14 -37
- package/dist/esm/src/codeGeneratorManager.d.ts +8 -0
- package/{src → dist/esm/src}/codeGeneratorManager.js +15 -24
- package/dist/esm/src/config/routes.d.ts +3 -0
- package/{src → dist/esm/src}/config/routes.js +40 -89
- package/dist/esm/src/configManager.d.ts +36 -0
- package/{src → dist/esm/src}/configManager.js +11 -40
- package/dist/esm/src/containerManager.d.ts +89 -0
- package/{src → dist/esm/src}/containerManager.js +81 -182
- package/dist/esm/src/filesystem/routes.d.ts +3 -0
- package/dist/esm/src/filesystem/routes.js +64 -0
- package/dist/esm/src/filesystemManager.d.ts +15 -0
- package/{src → dist/esm/src}/filesystemManager.js +20 -28
- package/dist/esm/src/identities/routes.d.ts +3 -0
- package/dist/esm/src/identities/routes.js +13 -0
- package/dist/esm/src/instanceManager.d.ts +56 -0
- package/{src → dist/esm/src}/instanceManager.js +88 -179
- package/dist/esm/src/instances/routes.d.ts +3 -0
- package/{src → dist/esm/src}/instances/routes.js +31 -70
- package/dist/esm/src/middleware/cors.d.ts +2 -0
- package/{src → dist/esm/src}/middleware/cors.js +2 -3
- package/dist/esm/src/middleware/kapeta.d.ts +11 -0
- package/{src → dist/esm/src}/middleware/kapeta.js +3 -7
- package/dist/esm/src/middleware/stringBody.d.ts +5 -0
- package/{src → dist/esm/src}/middleware/stringBody.js +2 -3
- package/dist/esm/src/networkManager.d.ts +32 -0
- package/{src → dist/esm/src}/networkManager.js +16 -33
- package/dist/esm/src/operatorManager.d.ts +36 -0
- package/{src → dist/esm/src}/operatorManager.js +35 -91
- package/dist/esm/src/progressListener.d.ts +20 -0
- package/dist/esm/src/progressListener.js +88 -0
- package/dist/esm/src/providerManager.d.ts +9 -0
- package/dist/esm/src/providerManager.js +45 -0
- package/dist/esm/src/providers/routes.d.ts +3 -0
- package/{src → dist/esm/src}/providers/routes.js +10 -16
- package/dist/esm/src/proxy/routes.d.ts +3 -0
- package/dist/esm/src/proxy/routes.js +106 -0
- package/dist/esm/src/proxy/types/rest.d.ts +4 -0
- package/dist/esm/src/proxy/types/rest.js +107 -0
- package/dist/esm/src/proxy/types/web.d.ts +4 -0
- package/{src → dist/esm/src}/proxy/types/web.js +13 -35
- package/dist/esm/src/repositoryManager.d.ts +17 -0
- package/dist/esm/src/repositoryManager.js +212 -0
- package/dist/esm/src/serviceManager.d.ts +29 -0
- package/{src → dist/esm/src}/serviceManager.js +12 -42
- package/dist/esm/src/socketManager.d.ts +14 -0
- package/{src → dist/esm/src}/socketManager.js +19 -23
- package/dist/esm/src/storageService.d.ts +17 -0
- package/{src → dist/esm/src}/storageService.js +8 -27
- package/dist/esm/src/traffic/routes.d.ts +3 -0
- package/{src → dist/esm/src}/traffic/routes.js +4 -9
- package/dist/esm/src/types.d.ts +88 -0
- package/dist/esm/src/types.js +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/{src → dist/esm/src}/utils/BlockInstanceRunner.js +137 -256
- package/dist/esm/src/utils/LogData.d.ts +19 -0
- package/{src → dist/esm/src}/utils/LogData.js +11 -22
- package/dist/esm/src/utils/pathTemplateParser.d.ts +26 -0
- package/{src → dist/esm/src}/utils/pathTemplateParser.js +21 -40
- package/dist/esm/src/utils/utils.d.ts +1 -0
- package/dist/esm/src/utils/utils.js +11 -0
- package/dist/esm/start.d.ts +1 -0
- package/dist/esm/start.js +7 -0
- package/index.ts +147 -0
- package/package.json +106 -74
- package/src/assetManager.ts +191 -0
- package/src/assets/routes.ts +132 -0
- package/src/clusterService.ts +134 -0
- package/src/codeGeneratorManager.ts +57 -0
- package/src/config/routes.ts +159 -0
- package/src/configManager.ts +148 -0
- package/src/containerManager.ts +466 -0
- package/src/filesystem/routes.ts +74 -0
- package/src/filesystemManager.ts +93 -0
- package/src/identities/routes.ts +20 -0
- package/src/instanceManager.ts +503 -0
- package/src/instances/routes.ts +164 -0
- package/src/middleware/cors.ts +9 -0
- package/src/middleware/kapeta.ts +27 -0
- package/src/middleware/stringBody.ts +16 -0
- package/src/networkManager.ts +137 -0
- package/src/operatorManager.ts +221 -0
- package/src/progressListener.ts +102 -0
- package/src/{providerManager.js → providerManager.ts} +15 -31
- package/src/providers/routes.ts +46 -0
- package/src/proxy/routes.ts +148 -0
- package/src/proxy/types/{rest.js → rest.ts} +30 -30
- package/src/proxy/types/web.ts +60 -0
- package/src/{repositoryManager.js → repositoryManager.ts} +49 -73
- package/src/serviceManager.ts +120 -0
- package/src/socketManager.ts +57 -0
- package/src/storageService.ts +88 -0
- package/src/traffic/routes.ts +18 -0
- package/src/types.ts +97 -0
- package/src/utils/BlockInstanceRunner.ts +555 -0
- package/src/utils/LogData.ts +47 -0
- package/src/utils/pathTemplateParser.ts +138 -0
- package/src/utils/utils.ts +12 -0
- package/start.ts +8 -0
- package/tsconfig.json +13 -0
- package/index.js +0 -127
- package/src/filesystem/routes.js +0 -74
- package/src/identities/routes.js +0 -19
- package/src/progressListener.js +0 -82
- package/src/proxy/routes.js +0 -126
- package/src/utils/utils.js +0 -13
- package/start.js +0 -7
@@ -1,92 +1,71 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
const configManager = require("./configManager");
|
12
|
-
|
1
|
+
import _ from 'lodash';
|
2
|
+
import request from 'request';
|
3
|
+
import EventEmitter from 'events';
|
4
|
+
import { BlockInstanceRunner } from './utils/BlockInstanceRunner';
|
5
|
+
import { storageService } from './storageService';
|
6
|
+
import { socketManager } from './socketManager';
|
7
|
+
import { serviceManager } from './serviceManager';
|
8
|
+
import { assetManager } from './assetManager';
|
9
|
+
import { containerManager } from './containerManager';
|
10
|
+
import { configManager } from './configManager';
|
13
11
|
const CHECK_INTERVAL = 10000;
|
14
12
|
const DEFAULT_HEALTH_PORT_TYPE = 'rest';
|
15
|
-
|
16
13
|
const EVENT_STATUS_CHANGED = 'status-changed';
|
17
14
|
const EVENT_INSTANCE_CREATED = 'instance-created';
|
18
15
|
const EVENT_INSTANCE_EXITED = 'instance-exited';
|
19
16
|
const EVENT_INSTANCE_LOG = 'instance-log';
|
20
|
-
|
21
17
|
const STATUS_STARTING = 'starting';
|
22
18
|
const STATUS_READY = 'ready';
|
23
19
|
const STATUS_UNHEALTHY = 'unhealthy';
|
24
20
|
const STATUS_STOPPED = 'stopped';
|
25
|
-
|
26
21
|
const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
|
27
|
-
|
28
22
|
class InstanceManager {
|
23
|
+
_interval;
|
24
|
+
/**
|
25
|
+
* Contains an array of running instances that have self-registered with this
|
26
|
+
* cluster service. This is done by the Kapeta SDKs
|
27
|
+
*/
|
28
|
+
_instances = [];
|
29
|
+
/**
|
30
|
+
* Contains the process info for the instances started by this manager. In memory only
|
31
|
+
* so can't be relied on for knowing everything that's running.
|
32
|
+
*
|
33
|
+
*/
|
34
|
+
_processes = {};
|
29
35
|
constructor() {
|
30
36
|
this._interval = setInterval(() => this._checkInstances(), CHECK_INTERVAL);
|
31
|
-
/**
|
32
|
-
* Contains an array of running instances that have self-registered with this
|
33
|
-
* cluster service. This is done by the Kapeta SDKs
|
34
|
-
*
|
35
|
-
* @type {any[]}
|
36
|
-
* @private
|
37
|
-
*/
|
38
37
|
this._instances = storageService.section('instances', []);
|
39
|
-
/**
|
40
|
-
* Contains the process info for the instances started by this manager. In memory only
|
41
|
-
* so can't be relied on for knowing everything that's running.
|
42
|
-
*
|
43
|
-
* @type {{[systemId:string]:{[instanceId:string]:ProcessInfo}}}
|
44
|
-
* @private
|
45
|
-
*/
|
46
38
|
this._processes = {};
|
47
|
-
|
48
39
|
this._checkInstances();
|
49
40
|
}
|
50
|
-
|
51
41
|
_save() {
|
52
42
|
storageService.put('instances', this._instances);
|
53
43
|
}
|
54
|
-
|
55
44
|
async _checkInstances() {
|
56
45
|
let changed = false;
|
57
46
|
for (let i = 0; i < this._instances.length; i++) {
|
58
47
|
const instance = this._instances[i];
|
59
|
-
|
60
48
|
const newStatus = await this._getInstanceStatus(instance);
|
61
|
-
|
62
|
-
if (newStatus === STATUS_UNHEALTHY &&
|
63
|
-
instance.status === STATUS_STARTING) {
|
49
|
+
if (newStatus === STATUS_UNHEALTHY && instance.status === STATUS_STARTING) {
|
64
50
|
// If instance is starting we consider unhealthy an indication
|
65
51
|
// that it is still starting
|
66
52
|
continue;
|
67
53
|
}
|
68
|
-
|
69
54
|
if (instance.status !== newStatus) {
|
70
55
|
instance.status = newStatus;
|
71
|
-
console.log(
|
72
|
-
'Instance status changed: %s %s -> %s',
|
73
|
-
instance.systemId, instance.instanceId, instance.status
|
74
|
-
)
|
56
|
+
console.log('Instance status changed: %s %s -> %s', instance.systemId, instance.instanceId, instance.status);
|
75
57
|
this._emit(instance.systemId, EVENT_STATUS_CHANGED, instance);
|
76
58
|
changed = true;
|
77
59
|
}
|
78
60
|
}
|
79
|
-
|
80
61
|
if (changed) {
|
81
62
|
this._save();
|
82
63
|
}
|
83
64
|
}
|
84
|
-
|
85
65
|
async _isRunning(instance) {
|
86
66
|
if (!instance.pid) {
|
87
67
|
return;
|
88
68
|
}
|
89
|
-
|
90
69
|
if (instance.type === 'docker') {
|
91
70
|
const container = await containerManager.get(instance.pid);
|
92
71
|
if (!container) {
|
@@ -95,64 +74,57 @@ class InstanceManager {
|
|
95
74
|
}
|
96
75
|
return await container.isRunning();
|
97
76
|
}
|
98
|
-
|
99
77
|
//Otherwise its just a normal process.
|
100
78
|
//TODO: Handle for Windows
|
101
79
|
try {
|
102
|
-
return process.kill(instance.pid, 0)
|
103
|
-
}
|
80
|
+
return process.kill(instance.pid, 0);
|
81
|
+
}
|
82
|
+
catch (err) {
|
104
83
|
return err.code === 'EPERM';
|
105
84
|
}
|
106
85
|
}
|
107
|
-
|
108
86
|
async _getInstanceStatus(instance) {
|
109
87
|
if (instance.status === STATUS_STOPPED) {
|
110
88
|
//Will only change when it reregisters
|
111
89
|
return STATUS_STOPPED;
|
112
90
|
}
|
113
|
-
|
114
|
-
if (!await this._isRunning(instance)) {
|
91
|
+
if (!(await this._isRunning(instance))) {
|
115
92
|
return STATUS_STOPPED;
|
116
93
|
}
|
117
|
-
|
118
94
|
if (!instance.health) {
|
119
95
|
//No health url means we assume it's healthy as soon as it's running
|
120
96
|
return STATUS_READY;
|
121
97
|
}
|
122
|
-
|
123
98
|
return new Promise((resolve) => {
|
99
|
+
if (!instance.health) {
|
100
|
+
resolve(STATUS_READY);
|
101
|
+
return;
|
102
|
+
}
|
124
103
|
request(instance.health, (err, response) => {
|
125
104
|
if (err) {
|
126
105
|
resolve(STATUS_UNHEALTHY);
|
127
106
|
return;
|
128
107
|
}
|
129
|
-
|
130
|
-
if (response.responseCode > 399) {
|
108
|
+
if (response.statusCode > 399) {
|
131
109
|
resolve(STATUS_UNHEALTHY);
|
132
110
|
return;
|
133
111
|
}
|
134
|
-
|
135
112
|
resolve(STATUS_READY);
|
136
113
|
});
|
137
114
|
});
|
138
115
|
}
|
139
|
-
|
140
116
|
getInstances() {
|
141
117
|
if (!this._instances) {
|
142
118
|
return [];
|
143
119
|
}
|
144
|
-
|
145
120
|
return [...this._instances];
|
146
121
|
}
|
147
|
-
|
148
122
|
getInstancesForPlan(systemId) {
|
149
123
|
if (!this._instances) {
|
150
124
|
return [];
|
151
125
|
}
|
152
|
-
|
153
|
-
return this._instances.filter(instance => instance.systemId === systemId);
|
126
|
+
return this._instances.filter((instance) => instance.systemId === systemId);
|
154
127
|
}
|
155
|
-
|
156
128
|
/**
|
157
129
|
* Get instance information
|
158
130
|
*
|
@@ -161,26 +133,19 @@ class InstanceManager {
|
|
161
133
|
* @return {*}
|
162
134
|
*/
|
163
135
|
getInstance(systemId, instanceId) {
|
164
|
-
return _.find(this._instances, {systemId, instanceId});
|
136
|
+
return _.find(this._instances, { systemId, instanceId });
|
165
137
|
}
|
166
|
-
|
167
138
|
/**
|
168
139
|
*
|
169
140
|
* @param {string} systemId
|
170
141
|
* @param {string} instanceId
|
171
|
-
* @param {
|
142
|
+
* @param {InstanceInfo} info
|
172
143
|
* @return {Promise<void>}
|
173
144
|
*/
|
174
145
|
async registerInstance(systemId, instanceId, info) {
|
175
146
|
let instance = this.getInstance(systemId, instanceId);
|
176
|
-
|
177
147
|
//Get target address
|
178
|
-
let address = await serviceManager.getProviderAddress(
|
179
|
-
systemId,
|
180
|
-
instanceId,
|
181
|
-
info.portType ?? DEFAULT_HEALTH_PORT_TYPE
|
182
|
-
);
|
183
|
-
|
148
|
+
let address = await serviceManager.getProviderAddress(systemId, instanceId, info.portType ?? DEFAULT_HEALTH_PORT_TYPE);
|
184
149
|
let healthUrl = null;
|
185
150
|
let health = info.health;
|
186
151
|
if (health) {
|
@@ -189,7 +154,6 @@ class InstanceManager {
|
|
189
154
|
}
|
190
155
|
healthUrl = address + health;
|
191
156
|
}
|
192
|
-
|
193
157
|
if (instance) {
|
194
158
|
instance.status = STATUS_STARTING;
|
195
159
|
instance.pid = info.pid;
|
@@ -201,7 +165,8 @@ class InstanceManager {
|
|
201
165
|
instance.health = healthUrl;
|
202
166
|
}
|
203
167
|
this._emit(systemId, EVENT_STATUS_CHANGED, instance);
|
204
|
-
}
|
168
|
+
}
|
169
|
+
else {
|
205
170
|
instance = {
|
206
171
|
systemId,
|
207
172
|
instanceId,
|
@@ -209,19 +174,15 @@ class InstanceManager {
|
|
209
174
|
pid: info.pid,
|
210
175
|
type: info.type,
|
211
176
|
health: healthUrl,
|
212
|
-
address
|
177
|
+
address,
|
213
178
|
};
|
214
|
-
|
215
179
|
this._instances.push(instance);
|
216
|
-
|
217
180
|
this._emit(systemId, EVENT_INSTANCE_CREATED, instance);
|
218
181
|
}
|
219
|
-
|
220
182
|
this._save();
|
221
183
|
}
|
222
|
-
|
223
184
|
setInstanceAsStopped(systemId, instanceId) {
|
224
|
-
const instance = _.find(this._instances, {systemId, instanceId});
|
185
|
+
const instance = _.find(this._instances, { systemId, instanceId });
|
225
186
|
if (instance) {
|
226
187
|
instance.status = STATUS_STOPPED;
|
227
188
|
instance.pid = null;
|
@@ -230,209 +191,171 @@ class InstanceManager {
|
|
230
191
|
this._save();
|
231
192
|
}
|
232
193
|
}
|
233
|
-
|
234
194
|
_emit(systemId, type, payload) {
|
235
|
-
|
195
|
+
try {
|
196
|
+
socketManager.emit(`${systemId}/instances`, type, payload);
|
197
|
+
}
|
198
|
+
catch (e) {
|
199
|
+
console.warn('Failed to emit instance event: %s', e.message);
|
200
|
+
}
|
236
201
|
}
|
237
|
-
|
238
|
-
/**
|
239
|
-
*
|
240
|
-
* @param planRef
|
241
|
-
* @return {Promise<ProcessInfo[]>}
|
242
|
-
*/
|
243
202
|
async createProcessesForPlan(planRef) {
|
244
203
|
await this.stopAllForPlan(planRef);
|
245
|
-
|
246
204
|
const plan = await assetManager.getPlan(planRef, true);
|
247
205
|
if (!plan) {
|
248
206
|
throw new Error('Plan not found: ' + planRef);
|
249
207
|
}
|
250
|
-
|
251
208
|
if (!plan.spec.blocks) {
|
252
209
|
console.warn('No blocks found in plan', planRef);
|
253
210
|
return [];
|
254
211
|
}
|
255
|
-
|
256
212
|
let promises = [];
|
257
213
|
let errors = [];
|
258
|
-
for(let blockInstance of Object.values(plan.spec.blocks)) {
|
214
|
+
for (let blockInstance of Object.values(plan.spec.blocks)) {
|
259
215
|
try {
|
260
216
|
promises.push(this.createProcess(planRef, blockInstance.id));
|
261
|
-
}
|
217
|
+
}
|
218
|
+
catch (e) {
|
262
219
|
errors.push(e);
|
263
220
|
}
|
264
221
|
}
|
265
|
-
|
266
222
|
const settled = await Promise.allSettled(promises);
|
267
|
-
|
268
223
|
if (errors.length > 0) {
|
269
224
|
throw errors[0];
|
270
225
|
}
|
271
|
-
|
272
|
-
return settled.map(p => p.value);
|
226
|
+
return settled.map((p) => (p.status === 'fulfilled' ? p.value : null)).filter((p) => !!p);
|
273
227
|
}
|
274
|
-
|
275
228
|
async _stopInstance(instance) {
|
276
229
|
if (!instance.pid) {
|
277
230
|
return;
|
278
231
|
}
|
279
|
-
|
280
232
|
if (instance.status === 'stopped') {
|
281
233
|
return;
|
282
234
|
}
|
283
|
-
|
284
235
|
try {
|
285
236
|
if (instance.type === 'docker') {
|
286
237
|
const container = await containerManager.get(instance.pid);
|
287
238
|
if (container) {
|
288
239
|
try {
|
289
240
|
await container.stop();
|
290
|
-
}
|
241
|
+
}
|
242
|
+
catch (e) {
|
291
243
|
console.error('Failed to stop container', e);
|
292
244
|
}
|
293
245
|
}
|
294
246
|
return;
|
295
247
|
}
|
296
248
|
process.kill(instance.pid, 'SIGTERM');
|
297
|
-
}
|
249
|
+
}
|
250
|
+
catch (e) {
|
298
251
|
console.error('Failed to stop process', e);
|
299
252
|
}
|
300
253
|
}
|
301
|
-
|
302
254
|
async stopAllForPlan(planRef) {
|
303
|
-
|
304
255
|
if (this._processes[planRef]) {
|
305
256
|
const promises = [];
|
306
257
|
console.log('Stopping all processes for plan', planRef);
|
307
|
-
for(let instance of Object.values(this._processes[planRef])) {
|
258
|
+
for (let instance of Object.values(this._processes[planRef])) {
|
308
259
|
promises.push(instance.stop());
|
309
260
|
}
|
310
|
-
|
311
261
|
await Promise.all(promises);
|
312
|
-
|
313
262
|
this._processes[planRef] = {};
|
314
263
|
}
|
315
|
-
|
316
264
|
//Also stop instances not being maintained by the cluster service
|
317
|
-
const instancesForPlan = this._instances
|
318
|
-
.filter(instance => instance.systemId === planRef);
|
319
|
-
|
265
|
+
const instancesForPlan = this._instances.filter((instance) => instance.systemId === planRef);
|
320
266
|
const promises = [];
|
321
|
-
for(let instance of instancesForPlan) {
|
267
|
+
for (let instance of instancesForPlan) {
|
322
268
|
promises.push(this._stopInstance(instance));
|
323
269
|
}
|
324
|
-
|
325
270
|
await Promise.all(promises);
|
326
271
|
}
|
327
|
-
|
328
|
-
/**
|
329
|
-
*
|
330
|
-
* @param planRef
|
331
|
-
* @param instanceId
|
332
|
-
* @return {Promise<PromiseInfo>}
|
333
|
-
*/
|
334
272
|
async createProcess(planRef, instanceId) {
|
335
273
|
const plan = await assetManager.getPlan(planRef, true);
|
336
274
|
if (!plan) {
|
337
275
|
throw new Error('Plan not found: ' + planRef);
|
338
276
|
}
|
339
|
-
|
340
|
-
const blockInstance = plan.spec && plan.spec.blocks ? _.find(plan.spec.blocks, {id: instanceId}) : null;
|
277
|
+
const blockInstance = plan.spec && plan.spec.blocks ? _.find(plan.spec.blocks, { id: instanceId }) : null;
|
341
278
|
if (!blockInstance) {
|
342
279
|
throw new Error('Block instance not found: ' + instanceId);
|
343
280
|
}
|
344
|
-
|
345
281
|
const blockRef = blockInstance.block.ref;
|
346
|
-
|
347
282
|
const blockAsset = await assetManager.getAsset(blockRef, true);
|
348
283
|
const instanceConfig = await configManager.getConfigForSection(planRef, instanceId);
|
349
|
-
|
350
284
|
if (!blockAsset) {
|
351
285
|
throw new Error('Block not found: ' + blockRef);
|
352
286
|
}
|
353
|
-
|
354
287
|
if (!this._processes[planRef]) {
|
355
288
|
this._processes[planRef] = {};
|
356
289
|
}
|
357
|
-
|
358
290
|
await this.stopProcess(planRef, instanceId);
|
359
291
|
const type = blockAsset.version === 'local' ? 'local' : 'docker';
|
360
|
-
|
361
292
|
const runner = new BlockInstanceRunner(planRef);
|
362
|
-
|
363
293
|
const startTime = Date.now();
|
364
294
|
try {
|
365
295
|
const process = await runner.start(blockRef, instanceId, instanceConfig);
|
366
296
|
//emit stdout/stderr via sockets
|
367
|
-
process.output.on(
|
297
|
+
process.output.on('data', (data) => {
|
368
298
|
const payload = {
|
369
|
-
source:
|
370
|
-
level:
|
299
|
+
source: 'stdout',
|
300
|
+
level: 'INFO',
|
371
301
|
message: data.toString(),
|
372
|
-
time: Date.now()
|
302
|
+
time: Date.now(),
|
373
303
|
};
|
374
304
|
this._emit(instanceId, EVENT_INSTANCE_LOG, payload);
|
375
305
|
});
|
376
|
-
|
377
306
|
process.output.on('exit', (exitCode) => {
|
378
307
|
const timeRunning = Date.now() - startTime;
|
379
308
|
const instance = this.getInstance(planRef, instanceId);
|
380
|
-
if (instance
|
309
|
+
if (instance?.status === STATUS_READY) {
|
381
310
|
//It's already been running
|
382
311
|
return;
|
383
312
|
}
|
384
|
-
|
385
|
-
if (exitCode === 143 ||
|
386
|
-
exitCode === 137) {
|
313
|
+
if (exitCode === 143 || exitCode === 137) {
|
387
314
|
//Process got SIGTERM (143) or SIGKILL (137)
|
388
315
|
//TODO: Windows?
|
389
316
|
return;
|
390
317
|
}
|
391
|
-
|
392
318
|
if (exitCode !== 0 || timeRunning < MIN_TIME_RUNNING) {
|
393
319
|
this._emit(blockInstance.id, EVENT_INSTANCE_EXITED, {
|
394
|
-
error:
|
320
|
+
error: 'Failed to start instance',
|
395
321
|
status: EVENT_INSTANCE_EXITED,
|
396
|
-
instanceId: blockInstance.id
|
322
|
+
instanceId: blockInstance.id,
|
397
323
|
});
|
398
324
|
}
|
399
325
|
});
|
400
|
-
|
401
326
|
await this.registerInstance(planRef, instanceId, {
|
402
327
|
type: process.type,
|
403
|
-
pid: process.pid,
|
328
|
+
pid: process.pid ?? -1,
|
404
329
|
health: null,
|
405
330
|
portType: process.portType,
|
331
|
+
status: STATUS_STARTING,
|
406
332
|
});
|
407
|
-
|
408
|
-
|
409
|
-
|
333
|
+
return (this._processes[planRef][instanceId] = process);
|
334
|
+
}
|
335
|
+
catch (e) {
|
410
336
|
console.warn('Failed to start instance', e);
|
411
337
|
const logs = [
|
412
338
|
{
|
413
|
-
source:
|
414
|
-
level:
|
339
|
+
source: 'stdout',
|
340
|
+
level: 'ERROR',
|
415
341
|
message: e.message,
|
416
|
-
time: Date.now()
|
417
|
-
}
|
342
|
+
time: Date.now(),
|
343
|
+
},
|
418
344
|
];
|
419
|
-
|
420
345
|
await this.registerInstance(planRef, instanceId, {
|
421
346
|
type: 'local',
|
422
347
|
pid: null,
|
423
348
|
health: null,
|
424
349
|
portType: DEFAULT_HEALTH_PORT_TYPE,
|
350
|
+
status: STATUS_UNHEALTHY,
|
425
351
|
});
|
426
|
-
|
427
352
|
this._emit(instanceId, EVENT_INSTANCE_LOG, logs[0]);
|
428
|
-
|
429
353
|
this._emit(blockInstance.id, EVENT_INSTANCE_EXITED, {
|
430
354
|
error: `Failed to start instance: ${e.message}`,
|
431
355
|
status: EVENT_INSTANCE_EXITED,
|
432
|
-
instanceId: blockInstance.id
|
356
|
+
instanceId: blockInstance.id,
|
433
357
|
});
|
434
|
-
|
435
|
-
return this._processes[planRef][instanceId] = {
|
358
|
+
return (this._processes[planRef][instanceId] = {
|
436
359
|
pid: -1,
|
437
360
|
type,
|
438
361
|
logs: () => logs,
|
@@ -440,12 +363,10 @@ class InstanceManager {
|
|
440
363
|
ref: blockRef,
|
441
364
|
id: instanceId,
|
442
365
|
name: blockInstance.name,
|
443
|
-
output: new EventEmitter()
|
444
|
-
};
|
366
|
+
output: new EventEmitter(),
|
367
|
+
});
|
445
368
|
}
|
446
|
-
|
447
369
|
}
|
448
|
-
|
449
370
|
/**
|
450
371
|
*
|
451
372
|
* @param {string} planRef
|
@@ -456,54 +377,42 @@ class InstanceManager {
|
|
456
377
|
if (!this._processes[planRef]) {
|
457
378
|
return null;
|
458
379
|
}
|
459
|
-
|
460
380
|
return this._processes[planRef][instanceId];
|
461
381
|
}
|
462
|
-
|
463
382
|
async restartIfRunning(planRef, instanceId) {
|
464
|
-
if (!this._processes[planRef] ||
|
465
|
-
!this._processes[planRef][instanceId]) {
|
383
|
+
if (!this._processes[planRef] || !this._processes[planRef][instanceId]) {
|
466
384
|
return;
|
467
385
|
}
|
468
|
-
|
469
386
|
// createProcess will stop the process first if it's running
|
470
387
|
return this.createProcess(planRef, instanceId);
|
471
388
|
}
|
472
|
-
|
473
389
|
async stopProcess(planRef, instanceId) {
|
474
390
|
if (!this._processes[planRef]) {
|
475
391
|
return;
|
476
392
|
}
|
477
|
-
|
478
393
|
if (this._processes[planRef][instanceId]) {
|
479
394
|
try {
|
480
395
|
await this._processes[planRef][instanceId].stop();
|
481
|
-
}
|
396
|
+
}
|
397
|
+
catch (e) {
|
482
398
|
console.error('Failed to stop process for instance: %s -> %s', planRef, instanceId, e);
|
483
399
|
}
|
484
400
|
delete this._processes[planRef][instanceId];
|
485
401
|
}
|
486
402
|
}
|
487
|
-
|
488
403
|
async stopAllProcesses() {
|
489
|
-
for(let processesForPlan of Object.values(this._processes)) {
|
490
|
-
for(let processInfo of Object.values(processesForPlan)) {
|
404
|
+
for (let processesForPlan of Object.values(this._processes)) {
|
405
|
+
for (let processInfo of Object.values(processesForPlan)) {
|
491
406
|
await processInfo.stop();
|
492
407
|
}
|
493
408
|
}
|
494
409
|
this._processes = {};
|
495
|
-
|
496
|
-
for(let instance of this._instances) {
|
410
|
+
for (let instance of this._instances) {
|
497
411
|
await this._stopInstance(instance);
|
498
412
|
}
|
499
413
|
}
|
500
414
|
}
|
501
|
-
|
502
|
-
|
503
|
-
const instanceManager = new InstanceManager();
|
504
|
-
|
415
|
+
export const instanceManager = new InstanceManager();
|
505
416
|
process.on('exit', async () => {
|
506
417
|
await instanceManager.stopAllProcesses();
|
507
418
|
});
|
508
|
-
|
509
|
-
module.exports = instanceManager;
|