teraslice 0.87.1 → 0.89.0

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.
Files changed (69) hide show
  1. package/cluster-service.js +24 -18
  2. package/dist/src/index.js +42 -0
  3. package/package.json +10 -14
  4. package/service.js +4 -6
  5. package/worker-service.js +6 -6
  6. package/index.js +0 -21
  7. package/lib/cluster/cluster_master.js +0 -164
  8. package/lib/cluster/node_master.js +0 -393
  9. package/lib/cluster/services/api.js +0 -581
  10. package/lib/cluster/services/assets.js +0 -211
  11. package/lib/cluster/services/cluster/backends/kubernetes/deployments/worker.hbs +0 -86
  12. package/lib/cluster/services/cluster/backends/kubernetes/index.js +0 -225
  13. package/lib/cluster/services/cluster/backends/kubernetes/jobs/execution_controller.hbs +0 -69
  14. package/lib/cluster/services/cluster/backends/kubernetes/k8s.js +0 -450
  15. package/lib/cluster/services/cluster/backends/kubernetes/k8sResource.js +0 -443
  16. package/lib/cluster/services/cluster/backends/kubernetes/k8sState.js +0 -67
  17. package/lib/cluster/services/cluster/backends/kubernetes/utils.js +0 -58
  18. package/lib/cluster/services/cluster/backends/native/index.js +0 -611
  19. package/lib/cluster/services/cluster/backends/native/messaging.js +0 -563
  20. package/lib/cluster/services/cluster/backends/state-utils.js +0 -49
  21. package/lib/cluster/services/cluster/index.js +0 -15
  22. package/lib/cluster/services/execution.js +0 -459
  23. package/lib/cluster/services/jobs.js +0 -303
  24. package/lib/config/default-sysconfig.js +0 -47
  25. package/lib/config/index.js +0 -32
  26. package/lib/config/schemas/system.js +0 -333
  27. package/lib/processors/save_file/index.js +0 -9
  28. package/lib/processors/save_file/processor.js +0 -17
  29. package/lib/processors/save_file/schema.js +0 -17
  30. package/lib/processors/script.js +0 -130
  31. package/lib/processors/stdout/index.js +0 -9
  32. package/lib/processors/stdout/processor.js +0 -19
  33. package/lib/processors/stdout/schema.js +0 -18
  34. package/lib/storage/analytics.js +0 -106
  35. package/lib/storage/assets.js +0 -275
  36. package/lib/storage/backends/elasticsearch_store.js +0 -567
  37. package/lib/storage/backends/mappings/analytics.json +0 -49
  38. package/lib/storage/backends/mappings/asset.json +0 -40
  39. package/lib/storage/backends/mappings/ex.json +0 -55
  40. package/lib/storage/backends/mappings/job.json +0 -31
  41. package/lib/storage/backends/mappings/state.json +0 -37
  42. package/lib/storage/execution.js +0 -331
  43. package/lib/storage/index.js +0 -16
  44. package/lib/storage/jobs.js +0 -97
  45. package/lib/storage/state.js +0 -302
  46. package/lib/utils/api_utils.js +0 -173
  47. package/lib/utils/asset_utils.js +0 -117
  48. package/lib/utils/date_utils.js +0 -58
  49. package/lib/utils/encoding_utils.js +0 -29
  50. package/lib/utils/events.js +0 -7
  51. package/lib/utils/file_utils.js +0 -118
  52. package/lib/utils/id_utils.js +0 -19
  53. package/lib/utils/port_utils.js +0 -83
  54. package/lib/workers/assets/loader.js +0 -109
  55. package/lib/workers/assets/spawn.js +0 -78
  56. package/lib/workers/context/execution-context.js +0 -16
  57. package/lib/workers/context/terafoundation-context.js +0 -10
  58. package/lib/workers/execution-controller/execution-analytics.js +0 -211
  59. package/lib/workers/execution-controller/index.js +0 -1033
  60. package/lib/workers/execution-controller/recovery.js +0 -188
  61. package/lib/workers/execution-controller/scheduler.js +0 -461
  62. package/lib/workers/execution-controller/slice-analytics.js +0 -115
  63. package/lib/workers/helpers/job.js +0 -93
  64. package/lib/workers/helpers/op-analytics.js +0 -22
  65. package/lib/workers/helpers/terafoundation.js +0 -43
  66. package/lib/workers/helpers/worker-shutdown.js +0 -187
  67. package/lib/workers/metrics/index.js +0 -139
  68. package/lib/workers/worker/index.js +0 -344
  69. package/lib/workers/worker/slice.js +0 -143
@@ -1,344 +0,0 @@
1
- 'use strict';
2
-
3
- const {
4
- get,
5
- getFullErrorStack,
6
- isFatalError,
7
- logError,
8
- pWhile
9
- } = require('@terascope/utils');
10
- const { ExecutionController, formatURL } = require('@terascope/teraslice-messaging');
11
- const { makeStateStore, makeAnalyticsStore } = require('../../storage');
12
- const { generateWorkerId, makeLogger } = require('../helpers/terafoundation');
13
- const { waitForWorkerShutdown } = require('../helpers/worker-shutdown');
14
- const Metrics = require('../metrics');
15
- const Slice = require('./slice');
16
-
17
- class Worker {
18
- constructor(context, executionContext) {
19
- const workerId = generateWorkerId(context);
20
- const logger = makeLogger(context, 'worker');
21
- const events = context.apis.foundation.getSystemEvents();
22
-
23
- const {
24
- slicer_port: slicerPort,
25
- slicer_hostname: slicerHostname,
26
- performance_metrics: performanceMetrics
27
- } = executionContext.config;
28
-
29
- const config = context.sysconfig.teraslice;
30
- const networkLatencyBuffer = get(config, 'network_latency_buffer');
31
- const actionTimeout = get(config, 'action_timeout');
32
- const workerDisconnectTimeout = get(config, 'worker_disconnect_timeout');
33
- const slicerTimeout = get(config, 'slicer_timeout');
34
- const shutdownTimeout = get(config, 'shutdown_timeout');
35
-
36
- this.client = new ExecutionController.Client({
37
- executionControllerUrl: formatURL(slicerHostname, slicerPort),
38
- workerId,
39
- networkLatencyBuffer,
40
- workerDisconnectTimeout,
41
- // the connect timeout should be set to the same timeout that will
42
- // cause the execution fail if no Workers connect
43
- connectTimeout: slicerTimeout,
44
- actionTimeout,
45
- logger
46
- });
47
-
48
- this.slice = new Slice(context, executionContext);
49
-
50
- this.metrics = performanceMetrics
51
- ? new Metrics({
52
- logger
53
- })
54
- : null;
55
-
56
- this.stores = {};
57
- this.executionContext = executionContext;
58
- this.shutdownTimeout = shutdownTimeout;
59
- this.context = context;
60
- this.workerId = workerId;
61
- this.logger = logger;
62
- this.events = events;
63
-
64
- this.isShuttingDown = false;
65
- this.isProcessing = false;
66
- this.isInitialized = false;
67
- this.shouldShutdown = false;
68
- this.forceShutdown = false;
69
- this.slicesProcessed = 0;
70
- }
71
-
72
- async initialize() {
73
- const { context } = this;
74
- this.isInitialized = true;
75
-
76
- const [stateStore, analyticsStore] = await Promise.all([
77
- makeStateStore(context),
78
- makeAnalyticsStore(context),
79
- ]);
80
-
81
- this.stores.stateStore = stateStore;
82
- this.slice.stateStore = stateStore;
83
- this.stores.analyticsStore = analyticsStore;
84
- this.slice.analyticsStore = analyticsStore;
85
-
86
- this.client.onServerShutdown(() => {
87
- this.logger.warn('Execution Controller shutdown, exiting...');
88
- this.shouldShutdown = true;
89
- });
90
-
91
- await this.client.start();
92
-
93
- // initialize the execution context next
94
- await this.executionContext.initialize();
95
-
96
- if (this.metrics != null) {
97
- await this.metrics.initialize();
98
- }
99
-
100
- const { exId } = this.executionContext;
101
- this.logger.info(`execution: ${exId} initialized worker`);
102
- }
103
-
104
- async run() {
105
- let running = false;
106
-
107
- const _run = async () => {
108
- running = true;
109
-
110
- try {
111
- await this.runOnce();
112
- } catch (err) {
113
- process.exitCode = 1;
114
- logError(this.logger, err, 'Worker must shutdown due to fatal error');
115
- this.forceShutdown = true;
116
- } finally {
117
- running = false;
118
- }
119
- };
120
-
121
- await new Promise((resolve) => {
122
- const interval = setInterval(() => {
123
- if (this.forceShutdown) {
124
- done();
125
- return;
126
- }
127
-
128
- if (running) return;
129
-
130
- if (this.isShuttingDown || this.shouldShutdown) {
131
- done();
132
- return;
133
- }
134
-
135
- _run();
136
- }, 5);
137
-
138
- function done() {
139
- clearInterval(interval);
140
- resolve();
141
- }
142
- });
143
- }
144
-
145
- async runOnce() {
146
- if (this.isShuttingDown || this.forceShutdown || this.shouldShutdown) return;
147
-
148
- this.logger.trace('waiting for new slice from execution controller');
149
- const msg = await this.client.waitForSlice(() => this.isShuttingDown);
150
-
151
- if (!msg) {
152
- this.logger.debug(`${this.workerId} worker is idle`);
153
- return;
154
- }
155
-
156
- this.isProcessing = true;
157
-
158
- let sentSliceComplete = false;
159
- const { slice_id: sliceId } = msg;
160
-
161
- try {
162
- await this.slice.initialize(msg);
163
-
164
- await this.slice.run();
165
-
166
- this.logger.info(`slice ${sliceId} completed`);
167
-
168
- await this._sendSliceComplete({
169
- slice: this.slice.slice,
170
- analytics: this.slice.analyticsData
171
- });
172
- sentSliceComplete = true;
173
-
174
- await this.executionContext.onSliceFinished(sliceId);
175
- } catch (err) {
176
- logError(this.logger, err, `slice ${sliceId} run error`);
177
-
178
- if (!sentSliceComplete) {
179
- await this._sendSliceComplete({
180
- slice: this.slice.slice,
181
- analytics: this.slice.analyticsData,
182
- error: getFullErrorStack(err)
183
- });
184
- }
185
-
186
- if (isFatalError(err)) {
187
- throw err;
188
- }
189
- }
190
-
191
- this.isProcessing = false;
192
- this.slicesProcessed += 1;
193
- }
194
-
195
- async shutdown(block, event, shutdownError) {
196
- if (this.isShutdown) return;
197
- if (!this.isInitialized) return;
198
- const { exId } = this.executionContext;
199
-
200
- if (this.isShuttingDown) {
201
- const msgs = [
202
- 'worker',
203
- `shutdown was called for ${exId}`,
204
- 'but it was already shutting down',
205
- block !== false ? ', will block until done' : ''
206
- ];
207
- this.logger.debug(msgs.join(' '));
208
-
209
- if (block !== false) {
210
- await waitForWorkerShutdown(this.context, 'worker:shutdown:complete');
211
- }
212
- return;
213
- }
214
-
215
- this.client.available = false;
216
- this.isShuttingDown = true;
217
-
218
- const shutdownErrs = [];
219
- const pushError = (err) => {
220
- shutdownErrs.push(err);
221
- };
222
-
223
- const extra = event ? ` due to event: ${event}` : '';
224
- this.logger.warn(`worker shutdown was called for execution ${exId}${extra}`);
225
-
226
- // set the slice to to failed to avoid
227
- // flushing the slice at the end
228
- // we need to check if this.executionContext.sliceState
229
- // in case a slice isn't currently active
230
- if (shutdownError && this.executionContext.sliceState) {
231
- this.executionContext.onSliceFailed();
232
- }
233
-
234
- // attempt to flush the slice
235
- // and wait for the slice to finish
236
- await Promise.all([
237
- this.slice.flush().catch(pushError),
238
- this._waitForSliceToFinish().catch(pushError)
239
- ]);
240
-
241
- this.events.emit('worker:shutdown');
242
- await this.executionContext.shutdown();
243
-
244
- // make sure ->run() resolves the promise
245
- this.forceShutdown = true;
246
-
247
- await Promise.all([
248
- (async () => {
249
- const stores = Object.values(this.stores);
250
- await Promise.all(stores.map((store) => store.shutdown(true).catch(pushError)));
251
- })(),
252
- (async () => {
253
- await this.slice.shutdown().catch(pushError);
254
- })(),
255
- (async () => {
256
- await this.client.shutdown().catch(pushError);
257
- })(),
258
- (async () => {
259
- if (this.metrics == null) return;
260
- await this.metrics.shutdown().catch(pushError);
261
- })()
262
- ]);
263
-
264
- const n = this.slicesProcessed;
265
- this.logger.warn(
266
- `worker ${this.workerId} is shutdown for execution ${exId}, processed ${n} slices`
267
- );
268
- this.isShutdown = true;
269
-
270
- if (shutdownErrs.length) {
271
- const errMsg = shutdownErrs.map((e) => e.stack).join(', and');
272
- const shutdownErr = new Error(`Failed to shutdown correctly: ${errMsg}`);
273
- this.events.emit(this.context, 'worker:shutdown:complete', shutdownErr);
274
- throw shutdownErr;
275
- }
276
-
277
- this.events.emit(this.context, 'worker:shutdown:complete');
278
- }
279
-
280
- _sendSliceComplete(payload) {
281
- return pWhile(async () => {
282
- try {
283
- await this.client.sendSliceComplete(payload);
284
- return true;
285
- } catch (err) {
286
- if (this.isShuttingDown) {
287
- throw err;
288
- } else {
289
- this.logger.warn(err);
290
- }
291
- }
292
- return false;
293
- });
294
- }
295
-
296
- _waitForSliceToFinish() {
297
- if (!this.isProcessing) return Promise.resolve();
298
-
299
- const { logger } = this;
300
- const startTime = Date.now();
301
-
302
- return new Promise((resolve, reject) => {
303
- let timeout;
304
- let interval;
305
- const done = (err) => {
306
- clearInterval(interval);
307
- clearTimeout(timeout);
308
- if (err) {
309
- reject(err);
310
- return;
311
- }
312
- resolve();
313
- };
314
-
315
- interval = setInterval(() => {
316
- const elapsed = (Date.now() - startTime) / 1000;
317
- if (!this.isProcessing) {
318
- logger.trace(
319
- `is done with current slice, shutdown counter took ${elapsed} seconds`
320
- );
321
- done();
322
- return;
323
- }
324
-
325
- /* istanbul ignore if */
326
- if (elapsed % 60 === 0) {
327
- logger.info(
328
- `shutdown sequence initiated, but is still processing. Will force shutdown in ${elapsed} seconds`
329
- );
330
- }
331
- }, 100);
332
-
333
- timeout = setTimeout(() => {
334
- const seconds = this.shutdownTimeout / 1000;
335
- const err = new Error(
336
- `Worker shutdown timeout after ${seconds} seconds, forcing shutdown`
337
- );
338
- done(err);
339
- }, this.shutdownTimeout);
340
- });
341
- }
342
- }
343
-
344
- module.exports = Worker;
@@ -1,143 +0,0 @@
1
- 'use strict';
2
-
3
- const { TSError, getTypeOf, logError } = require('@terascope/utils');
4
- const { SliceState } = require('../../storage');
5
- const { makeLogger } = require('../helpers/terafoundation');
6
- const { logOpStats } = require('../helpers/op-analytics');
7
-
8
- class Slice {
9
- constructor(context, executionContext) {
10
- this.context = context;
11
- this.events = context.apis.foundation.getSystemEvents();
12
- this.executionContext = executionContext;
13
- }
14
-
15
- async initialize(slice) {
16
- const { slice_id: sliceId } = slice;
17
-
18
- if (slice.state !== SliceState.pending) {
19
- await this.stateStore.updateState(slice, SliceState.start);
20
- }
21
-
22
- this.slice = slice;
23
- this.logger = makeLogger(this.context, 'slice', {
24
- slice_id: sliceId
25
- });
26
-
27
- await this.executionContext.initializeSlice(slice);
28
- }
29
-
30
- async run() {
31
- if (this._isShutdown) throw new Error('Slice is already shutdown');
32
-
33
- const { slice } = this;
34
-
35
- let result;
36
- let sliceSuccess = false;
37
-
38
- try {
39
- result = await this.executionContext.runSlice();
40
- sliceSuccess = true;
41
- await this._markCompleted();
42
- } catch (_err) {
43
- const err = _err || new Error(`Unknown slice error, got ${getTypeOf(_err)} error`);
44
- // avoid incorrectly marking
45
- // the slice as failed when it fails
46
- // to mark it as "complete"
47
- if (!sliceSuccess) {
48
- await this._markFailed(err);
49
- }
50
- throw err;
51
- } finally {
52
- if (result) await this._logAnalytics(result.analytics, result.status);
53
- await this._onSliceFinalize(slice);
54
- }
55
-
56
- return result.results;
57
- }
58
-
59
- async flush() {
60
- const result = await this.executionContext.flush();
61
-
62
- if (result) {
63
- await this._markCompleted();
64
- await this._logAnalytics(result.analytics, result.status);
65
- await this._onSliceFinalize(this.slice);
66
- }
67
- }
68
-
69
- async shutdown() {
70
- this._isShutdown = true;
71
- }
72
-
73
- async _onSliceFinalize(slice) {
74
- try {
75
- await this.executionContext.onSliceFinalizing();
76
- } catch (err) {
77
- this.logger.error(
78
- new TSError(err, {
79
- reason: `Slice: ${slice.slice_id} failure on lifecycle event onSliceFinalizing`
80
- })
81
- );
82
- }
83
- }
84
-
85
- async _onSliceFailure(slice) {
86
- try {
87
- await this.executionContext.onSliceFailed();
88
- } catch (err) {
89
- this.logger.error(
90
- new TSError(err, {
91
- reason: `Slice: ${slice.slice_id} failure on lifecycle event onSliceFailed`
92
- })
93
- );
94
- }
95
- }
96
-
97
- async _logAnalytics(analyticsData, state) {
98
- if (analyticsData == null) return;
99
- this.analyticsData = analyticsData;
100
-
101
- logOpStats(this.logger, this.slice, this.analyticsData);
102
-
103
- try {
104
- await this.analyticsStore.log(
105
- this.executionContext,
106
- this.slice,
107
- this.analyticsData,
108
- state
109
- );
110
- } catch (_err) {
111
- this.logger.error(
112
- new TSError(_err, {
113
- reason: 'Failure to update analytics'
114
- })
115
- );
116
- }
117
- }
118
-
119
- async _markCompleted() {
120
- const { slice } = this;
121
-
122
- await this.stateStore.updateState(slice, SliceState.completed);
123
-
124
- this.logger.trace(`completed slice for execution: ${this.executionContext.exId}`, slice);
125
- this.events.emit('slice:success', slice);
126
- }
127
-
128
- async _markFailed(err) {
129
- const { stateStore, slice } = this;
130
-
131
- await stateStore.updateState(slice, SliceState.error, err);
132
-
133
- logError(this.logger, err, `slice state for ${this.executionContext.exId} has been marked as error`);
134
-
135
- await this._onSliceFailure(slice);
136
-
137
- throw new TSError(err, {
138
- reason: 'Slice failed processing'
139
- });
140
- }
141
- }
142
-
143
- module.exports = Slice;