teraslice 3.3.0 → 3.3.2
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/LICENSE +202 -0
- package/package.json +25 -28
- package/dist/src/interfaces.js +0 -12
- package/dist/src/lib/cluster/cluster_master.js +0 -246
- package/dist/src/lib/cluster/node_master.js +0 -355
- package/dist/src/lib/cluster/services/api.js +0 -663
- package/dist/src/lib/cluster/services/assets.js +0 -224
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/index.js +0 -192
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/interfaces.js +0 -2
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8s.js +0 -419
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sDeploymentResource.js +0 -60
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sJobResource.js +0 -55
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sResource.js +0 -357
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sServiceResource.js +0 -37
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/k8sState.js +0 -60
- package/dist/src/lib/cluster/services/cluster/backends/kubernetesV2/utils.js +0 -170
- package/dist/src/lib/cluster/services/cluster/backends/native/dispatch.js +0 -13
- package/dist/src/lib/cluster/services/cluster/backends/native/index.js +0 -526
- package/dist/src/lib/cluster/services/cluster/backends/native/messaging.js +0 -548
- package/dist/src/lib/cluster/services/cluster/backends/state-utils.js +0 -26
- package/dist/src/lib/cluster/services/cluster/index.js +0 -13
- package/dist/src/lib/cluster/services/execution.js +0 -435
- package/dist/src/lib/cluster/services/index.js +0 -6
- package/dist/src/lib/cluster/services/interfaces.js +0 -2
- package/dist/src/lib/cluster/services/jobs.js +0 -458
- package/dist/src/lib/config/default-sysconfig.js +0 -25
- package/dist/src/lib/config/index.js +0 -20
- package/dist/src/lib/config/schemas/system.js +0 -360
- package/dist/src/lib/storage/analytics.js +0 -86
- package/dist/src/lib/storage/assets.js +0 -401
- package/dist/src/lib/storage/backends/elasticsearch_store.js +0 -496
- package/dist/src/lib/storage/backends/mappings/analytics.js +0 -20
- package/dist/src/lib/storage/backends/mappings/asset.js +0 -32
- package/dist/src/lib/storage/backends/mappings/ex.js +0 -53
- package/dist/src/lib/storage/backends/mappings/job.js +0 -42
- package/dist/src/lib/storage/backends/mappings/state.js +0 -16
- package/dist/src/lib/storage/backends/s3_store.js +0 -237
- package/dist/src/lib/storage/execution.js +0 -302
- package/dist/src/lib/storage/index.js +0 -7
- package/dist/src/lib/storage/jobs.js +0 -81
- package/dist/src/lib/storage/state.js +0 -254
- package/dist/src/lib/utils/api_utils.js +0 -128
- package/dist/src/lib/utils/asset_utils.js +0 -94
- package/dist/src/lib/utils/date_utils.js +0 -52
- package/dist/src/lib/utils/encoding_utils.js +0 -27
- package/dist/src/lib/utils/events.js +0 -4
- package/dist/src/lib/utils/file_utils.js +0 -124
- package/dist/src/lib/utils/id_utils.js +0 -15
- package/dist/src/lib/utils/port_utils.js +0 -32
- package/dist/src/lib/workers/assets/index.js +0 -3
- package/dist/src/lib/workers/assets/loader-executable.js +0 -40
- package/dist/src/lib/workers/assets/loader.js +0 -73
- package/dist/src/lib/workers/assets/spawn.js +0 -55
- package/dist/src/lib/workers/context/execution-context.js +0 -12
- package/dist/src/lib/workers/context/terafoundation-context.js +0 -8
- package/dist/src/lib/workers/execution-controller/execution-analytics.js +0 -188
- package/dist/src/lib/workers/execution-controller/index.js +0 -1024
- package/dist/src/lib/workers/execution-controller/recovery.js +0 -151
- package/dist/src/lib/workers/execution-controller/scheduler.js +0 -390
- package/dist/src/lib/workers/execution-controller/slice-analytics.js +0 -96
- package/dist/src/lib/workers/helpers/job.js +0 -80
- package/dist/src/lib/workers/helpers/op-analytics.js +0 -22
- package/dist/src/lib/workers/helpers/terafoundation.js +0 -34
- package/dist/src/lib/workers/helpers/worker-shutdown.js +0 -147
- package/dist/src/lib/workers/metrics/index.js +0 -108
- package/dist/src/lib/workers/worker/index.js +0 -378
- package/dist/src/lib/workers/worker/slice.js +0 -122
- package/dist/test/config/schemas/system_schema-spec.js +0 -26
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8s-v2-spec.js +0 -458
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sResource-v2-spec.js +0 -818
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-multicluster-v2-spec.js +0 -67
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/k8sState-v2-spec.js +0 -84
- package/dist/test/lib/cluster/services/cluster/backends/kubernetes/v2/utils-v2-spec.js +0 -320
- package/dist/test/lib/cluster/services/cluster/backends/state-utils-spec.js +0 -37
- package/dist/test/node_master-spec.js +0 -194
- package/dist/test/services/api-spec.js +0 -79
- package/dist/test/services/assets-spec.js +0 -158
- package/dist/test/services/messaging-spec.js +0 -440
- package/dist/test/storage/assets_storage-spec.js +0 -95
- package/dist/test/storage/s3_store-spec.js +0 -149
- package/dist/test/test.config.js +0 -23
- package/dist/test/test.setup.js +0 -6
- package/dist/test/utils/api_utils-spec.js +0 -25
- package/dist/test/utils/asset_utils-spec.js +0 -141
- package/dist/test/utils/elastic_utils-spec.js +0 -25
- package/dist/test/workers/execution-controller/execution-controller-spec.js +0 -371
- package/dist/test/workers/execution-controller/execution-special-test-cases-spec.js +0 -519
- package/dist/test/workers/execution-controller/execution-test-cases-spec.js +0 -343
- package/dist/test/workers/execution-controller/recovery-spec.js +0 -160
- package/dist/test/workers/execution-controller/scheduler-spec.js +0 -249
- package/dist/test/workers/execution-controller/slice-analytics-spec.js +0 -121
- package/dist/test/workers/fixtures/ops/example-op/processor.js +0 -20
- package/dist/test/workers/fixtures/ops/example-op/schema.js +0 -19
- package/dist/test/workers/fixtures/ops/example-reader/fetcher.js +0 -20
- package/dist/test/workers/fixtures/ops/example-reader/schema.js +0 -41
- package/dist/test/workers/fixtures/ops/example-reader/slicer.js +0 -37
- package/dist/test/workers/fixtures/ops/new-op/processor.js +0 -29
- package/dist/test/workers/fixtures/ops/new-op/schema.js +0 -18
- package/dist/test/workers/fixtures/ops/new-reader/fetcher.js +0 -19
- package/dist/test/workers/fixtures/ops/new-reader/schema.js +0 -23
- package/dist/test/workers/fixtures/ops/new-reader/slicer.js +0 -13
- package/dist/test/workers/helpers/configs.js +0 -128
- package/dist/test/workers/helpers/execution-controller-helper.js +0 -49
- package/dist/test/workers/helpers/index.js +0 -5
- package/dist/test/workers/helpers/test-context.js +0 -210
- package/dist/test/workers/helpers/zip-directory.js +0 -25
- package/dist/test/workers/worker/slice-spec.js +0 -333
- package/dist/test/workers/worker/worker-spec.js +0 -356
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { times } from '@terascope/core-utils';
|
|
3
|
-
import { SliceExecution } from '../../../src/lib/workers/worker/slice.js';
|
|
4
|
-
import { TestContext } from '../helpers/index.js';
|
|
5
|
-
describe('Slice', () => {
|
|
6
|
-
async function setupSlice(testContext, eventMocks = {}) {
|
|
7
|
-
await testContext.initialize();
|
|
8
|
-
await testContext.executionContext.initialize();
|
|
9
|
-
const [stateStore, analyticsStore] = await Promise.all([
|
|
10
|
-
testContext.addStateStore(),
|
|
11
|
-
testContext.addAnalyticsStore(),
|
|
12
|
-
]);
|
|
13
|
-
const slice = new SliceExecution(testContext.context, testContext.executionContext, stateStore, analyticsStore);
|
|
14
|
-
testContext.attachCleanup(() => slice.shutdown());
|
|
15
|
-
const sliceConfig = await testContext.newSlice();
|
|
16
|
-
await slice.initialize(sliceConfig);
|
|
17
|
-
eventMocks['slice:success'] = jest.fn();
|
|
18
|
-
eventMocks['slice:finalize'] = jest.fn();
|
|
19
|
-
eventMocks['slice:failure'] = jest.fn();
|
|
20
|
-
eventMocks['slice:retry'] = jest.fn();
|
|
21
|
-
Object.keys(eventMocks).forEach((name) => {
|
|
22
|
-
const mock = eventMocks[name];
|
|
23
|
-
slice.events.on(name, mock);
|
|
24
|
-
});
|
|
25
|
-
return slice;
|
|
26
|
-
}
|
|
27
|
-
describe('with analytics', () => {
|
|
28
|
-
describe('when the slice succeeds', () => {
|
|
29
|
-
let slice;
|
|
30
|
-
let results;
|
|
31
|
-
let testContext;
|
|
32
|
-
const eventMocks = {};
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
testContext = new TestContext({ analytics: true });
|
|
35
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
36
|
-
results = await slice.run();
|
|
37
|
-
await Promise.all([
|
|
38
|
-
slice.stateStorage.refresh(),
|
|
39
|
-
slice.analyticsStorage.refresh(),
|
|
40
|
-
]);
|
|
41
|
-
});
|
|
42
|
-
afterEach(async () => {
|
|
43
|
-
await testContext.cleanup();
|
|
44
|
-
});
|
|
45
|
-
it('should handle the slice correctly', () => {
|
|
46
|
-
// should call of the operations
|
|
47
|
-
expect(results).toEqual(times(10, () => ({ hi: true })));
|
|
48
|
-
// should have the correct analytics data
|
|
49
|
-
expect(slice.analyticsData).toBeObject();
|
|
50
|
-
expect(slice.analyticsData.memory).toBeArrayOfSize(2);
|
|
51
|
-
expect(slice.analyticsData.size).toBeArrayOfSize(2);
|
|
52
|
-
expect(slice.analyticsData.time).toBeArrayOfSize(2);
|
|
53
|
-
// should call the correct events
|
|
54
|
-
expect(eventMocks['slice:success']).toHaveBeenCalledTimes(1);
|
|
55
|
-
expect(eventMocks['slice:success']).toHaveBeenCalled();
|
|
56
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
57
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalled();
|
|
58
|
-
expect(eventMocks['slice:failure']).not.toHaveBeenCalled();
|
|
59
|
-
expect(eventMocks['slice:retry']).not.toHaveBeenCalled();
|
|
60
|
-
// should have the correct state storage
|
|
61
|
-
const { exId } = slice.executionContext;
|
|
62
|
-
const query = `ex_id:${exId} AND state:completed`;
|
|
63
|
-
return expect(slice.stateStorage.count(query)).resolves.toEqual(1);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
describe('without analytics', () => {
|
|
68
|
-
describe('when the slice succeeds', () => {
|
|
69
|
-
let slice;
|
|
70
|
-
let results;
|
|
71
|
-
let testContext;
|
|
72
|
-
const eventMocks = {};
|
|
73
|
-
beforeEach(async () => {
|
|
74
|
-
testContext = new TestContext({ analytics: false });
|
|
75
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
76
|
-
results = await slice.run();
|
|
77
|
-
await Promise.all([
|
|
78
|
-
slice.stateStorage.refresh(),
|
|
79
|
-
slice.analyticsStorage.refresh(),
|
|
80
|
-
]);
|
|
81
|
-
});
|
|
82
|
-
afterEach(async () => {
|
|
83
|
-
await testContext.cleanup();
|
|
84
|
-
});
|
|
85
|
-
it('should handle the slice correctly', () => {
|
|
86
|
-
// should call all of the operations
|
|
87
|
-
expect(results).toEqual(times(10, () => ({ hi: true })));
|
|
88
|
-
// should have have the analytics data
|
|
89
|
-
expect(slice.analyticsData).toBeUndefined();
|
|
90
|
-
// should call the correct events
|
|
91
|
-
expect(eventMocks['slice:success']).toHaveBeenCalledTimes(1);
|
|
92
|
-
expect(eventMocks['slice:success']).toHaveBeenCalled();
|
|
93
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
94
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalled();
|
|
95
|
-
expect(eventMocks['slice:retry']).not.toHaveBeenCalled();
|
|
96
|
-
expect(eventMocks['slice:failure']).not.toHaveBeenCalled();
|
|
97
|
-
// should have the correct state storage
|
|
98
|
-
const { exId } = slice.executionContext;
|
|
99
|
-
const query = `ex_id:${exId} AND state:completed`;
|
|
100
|
-
return expect(slice.stateStorage.count(query, 0)).resolves.toEqual(1);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
describe('when the slice retries', () => {
|
|
104
|
-
let slice;
|
|
105
|
-
let results;
|
|
106
|
-
let testContext;
|
|
107
|
-
const eventMocks = {};
|
|
108
|
-
beforeEach(async () => {
|
|
109
|
-
testContext = new TestContext({
|
|
110
|
-
maxRetries: 3,
|
|
111
|
-
analytics: false,
|
|
112
|
-
readerErrorAt: [0]
|
|
113
|
-
});
|
|
114
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
115
|
-
results = await slice.run();
|
|
116
|
-
await Promise.all([
|
|
117
|
-
slice.stateStorage.refresh(),
|
|
118
|
-
slice.analyticsStorage.refresh(),
|
|
119
|
-
]);
|
|
120
|
-
});
|
|
121
|
-
afterEach(async () => {
|
|
122
|
-
await testContext.cleanup();
|
|
123
|
-
});
|
|
124
|
-
it('should handle the slice correctly', () => {
|
|
125
|
-
expect(results).toEqual(times(10, () => ({ hi: true })));
|
|
126
|
-
// should have have the analytics data
|
|
127
|
-
expect(slice.analyticsData).toBeUndefined();
|
|
128
|
-
// should call the correct events
|
|
129
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledTimes(1);
|
|
130
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledWith(slice.slice);
|
|
131
|
-
expect(eventMocks['slice:success']).toHaveBeenCalledTimes(1);
|
|
132
|
-
expect(eventMocks['slice:success']).toHaveBeenCalledWith(slice.slice);
|
|
133
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
134
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledWith(slice.slice);
|
|
135
|
-
expect(eventMocks['slice:failure']).not.toHaveBeenCalled();
|
|
136
|
-
// should have the correct state storage
|
|
137
|
-
const { exId } = slice.executionContext;
|
|
138
|
-
const query = `ex_id:${exId} AND state:completed`;
|
|
139
|
-
return expect(slice.stateStorage.count(query, 0)).resolves.toEqual(1);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
describe('when the slice fails to retry', () => {
|
|
143
|
-
let slice;
|
|
144
|
-
let err;
|
|
145
|
-
let testContext;
|
|
146
|
-
const eventMocks = {};
|
|
147
|
-
beforeEach(async () => {
|
|
148
|
-
testContext = new TestContext({
|
|
149
|
-
maxRetries: 3,
|
|
150
|
-
analytics: false,
|
|
151
|
-
newOps: true,
|
|
152
|
-
failOnSliceRetry: true
|
|
153
|
-
});
|
|
154
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
155
|
-
try {
|
|
156
|
-
await slice.run();
|
|
157
|
-
}
|
|
158
|
-
catch (_err) {
|
|
159
|
-
err = _err;
|
|
160
|
-
}
|
|
161
|
-
await Promise.all([
|
|
162
|
-
slice.stateStorage.refresh(),
|
|
163
|
-
slice.analyticsStorage.refresh(),
|
|
164
|
-
]);
|
|
165
|
-
});
|
|
166
|
-
afterEach(async () => {
|
|
167
|
-
await testContext.cleanup();
|
|
168
|
-
});
|
|
169
|
-
it('should handle the slice correctly', () => {
|
|
170
|
-
// should have reject with the error
|
|
171
|
-
expect(err).toBeDefined();
|
|
172
|
-
const errMsg = err.toString();
|
|
173
|
-
expect(errMsg).toInclude('Slice failed to retry');
|
|
174
|
-
expect(errMsg).toInclude('I will not allow it');
|
|
175
|
-
// should emit the events
|
|
176
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledTimes(1);
|
|
177
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledWith(slice.slice);
|
|
178
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledTimes(1);
|
|
179
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledWith(slice.slice);
|
|
180
|
-
expect(eventMocks['slice:success']).not.toHaveBeenCalled();
|
|
181
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
182
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledWith(slice.slice);
|
|
183
|
-
// should have the correct state storage
|
|
184
|
-
const { exId } = slice.executionContext;
|
|
185
|
-
const query = `ex_id:${exId} AND state:error`;
|
|
186
|
-
return expect(slice.stateStorage.count(query, 0)).resolves.toEqual(1);
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
describe('when the slice fails', () => {
|
|
190
|
-
let slice;
|
|
191
|
-
let testContext;
|
|
192
|
-
const eventMocks = {};
|
|
193
|
-
let err;
|
|
194
|
-
beforeEach(async () => {
|
|
195
|
-
testContext = new TestContext({
|
|
196
|
-
maxRetries: 5,
|
|
197
|
-
analytics: false,
|
|
198
|
-
opErrorAt: times(6)
|
|
199
|
-
});
|
|
200
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
201
|
-
try {
|
|
202
|
-
await slice.run();
|
|
203
|
-
}
|
|
204
|
-
catch (_err) {
|
|
205
|
-
err = _err;
|
|
206
|
-
}
|
|
207
|
-
await Promise.all([
|
|
208
|
-
slice.stateStorage.refresh(),
|
|
209
|
-
slice.analyticsStorage.refresh(),
|
|
210
|
-
]);
|
|
211
|
-
});
|
|
212
|
-
afterEach(async () => {
|
|
213
|
-
await testContext.cleanup();
|
|
214
|
-
});
|
|
215
|
-
it('should handle the slice correctly', () => {
|
|
216
|
-
// should have reject with the error
|
|
217
|
-
expect(err).toBeDefined();
|
|
218
|
-
expect(err.toString()).toStartWith('TSError: Slice failed processing, caused by TSError: Bad news bears');
|
|
219
|
-
// should emit the events
|
|
220
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledTimes(5);
|
|
221
|
-
expect(eventMocks['slice:retry']).toHaveBeenCalledWith(slice.slice);
|
|
222
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledTimes(1);
|
|
223
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledWith(slice.slice);
|
|
224
|
-
expect(eventMocks['slice:success']).not.toHaveBeenCalled();
|
|
225
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
226
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledWith(slice.slice);
|
|
227
|
-
// should have the correct state storage
|
|
228
|
-
const { exId } = slice.executionContext;
|
|
229
|
-
const query = `ex_id:${exId} AND state:error`;
|
|
230
|
-
return expect(slice.stateStorage.count(query, 0)).resolves.toEqual(1);
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
describe('when the slice fails with zero retries', () => {
|
|
234
|
-
let slice;
|
|
235
|
-
let testContext;
|
|
236
|
-
const eventMocks = {};
|
|
237
|
-
let err;
|
|
238
|
-
beforeEach(async () => {
|
|
239
|
-
testContext = new TestContext({
|
|
240
|
-
maxRetries: 0,
|
|
241
|
-
analytics: false,
|
|
242
|
-
opErrorAt: times(5)
|
|
243
|
-
});
|
|
244
|
-
slice = await setupSlice(testContext, eventMocks);
|
|
245
|
-
try {
|
|
246
|
-
await slice.run();
|
|
247
|
-
}
|
|
248
|
-
catch (_err) {
|
|
249
|
-
err = _err;
|
|
250
|
-
}
|
|
251
|
-
await Promise.all([
|
|
252
|
-
slice.stateStorage.refresh(),
|
|
253
|
-
slice.analyticsStorage.refresh(),
|
|
254
|
-
]);
|
|
255
|
-
});
|
|
256
|
-
afterEach(async () => {
|
|
257
|
-
await testContext.cleanup();
|
|
258
|
-
});
|
|
259
|
-
it('should handle the slice correctly', () => {
|
|
260
|
-
// should have reject with the error
|
|
261
|
-
expect(err).toBeDefined();
|
|
262
|
-
expect(err.toString()).toStartWith('TSError: Slice failed processing, caused by TSError: Bad news bears');
|
|
263
|
-
// should emit the events
|
|
264
|
-
expect(eventMocks['slice:retry']).not.toHaveBeenCalled();
|
|
265
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledTimes(1);
|
|
266
|
-
expect(eventMocks['slice:failure']).toHaveBeenCalledWith(slice.slice);
|
|
267
|
-
expect(eventMocks['slice:success']).not.toHaveBeenCalled();
|
|
268
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledTimes(1);
|
|
269
|
-
expect(eventMocks['slice:finalize']).toHaveBeenCalledWith(slice.slice);
|
|
270
|
-
// should have the correct state storage
|
|
271
|
-
const { exId } = slice.executionContext;
|
|
272
|
-
const query = `ex_id:${exId} AND state:error`;
|
|
273
|
-
return expect(slice.stateStorage.count(query, 0)).resolves.toEqual(1);
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
describe('when logging the analytics state', () => {
|
|
278
|
-
describe('when given invalid state', () => {
|
|
279
|
-
let testContext;
|
|
280
|
-
let slice;
|
|
281
|
-
beforeEach(async () => {
|
|
282
|
-
testContext = new TestContext({ analytics: true });
|
|
283
|
-
slice = await setupSlice(testContext);
|
|
284
|
-
});
|
|
285
|
-
afterEach(async () => {
|
|
286
|
-
await testContext.cleanup();
|
|
287
|
-
});
|
|
288
|
-
it('should not throw an error if given invalid state', async () => {
|
|
289
|
-
const data = { should: 'break' };
|
|
290
|
-
await expect(slice._logAnalytics(data)).resolves.not.toThrow();
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
describe('when the slice is a string', () => {
|
|
294
|
-
let testContext;
|
|
295
|
-
let slice;
|
|
296
|
-
beforeEach(async () => {
|
|
297
|
-
testContext = new TestContext({ analytics: true });
|
|
298
|
-
slice = await setupSlice(testContext);
|
|
299
|
-
slice.slice = 'hello-there';
|
|
300
|
-
});
|
|
301
|
-
afterEach(async () => {
|
|
302
|
-
await testContext.cleanup();
|
|
303
|
-
});
|
|
304
|
-
it('should handle the case when the slice is a string', async () => {
|
|
305
|
-
// TODO: this is not actually testing a string
|
|
306
|
-
await expect(slice._logAnalytics({})).resolves.not.toThrow();
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
describe('when marking an invalid slice', () => {
|
|
311
|
-
let testContext;
|
|
312
|
-
let slice;
|
|
313
|
-
beforeEach(async () => {
|
|
314
|
-
testContext = new TestContext();
|
|
315
|
-
slice = await setupSlice(testContext);
|
|
316
|
-
slice.slice = { should: 'break' };
|
|
317
|
-
});
|
|
318
|
-
afterEach(async () => {
|
|
319
|
-
await testContext.cleanup();
|
|
320
|
-
});
|
|
321
|
-
it('should throw an error when marking it as failed', async () => {
|
|
322
|
-
// @ts-expect-error
|
|
323
|
-
await expect(slice._markFailed(new Error('some error'))).rejects.toThrow(/Failure to update error state/);
|
|
324
|
-
// @ts-expect-error
|
|
325
|
-
await expect(slice._markFailed()).rejects.toThrow(/Failure to update error state/);
|
|
326
|
-
});
|
|
327
|
-
it('should throw an error when marking it as complete', async () => {
|
|
328
|
-
// @ts-expect-error
|
|
329
|
-
await expect(slice._markCompleted()).rejects.toThrow(/Failure to update completed state/);
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
});
|
|
333
|
-
//# sourceMappingURL=slice-spec.js.map
|
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import 'jest-extended';
|
|
3
|
-
import { pDelay } from '@terascope/core-utils';
|
|
4
|
-
import { ExecutionController } from '@terascope/teraslice-messaging';
|
|
5
|
-
import { findPort } from '../../../src/lib/utils/port_utils.js';
|
|
6
|
-
import { Worker } from '../../../src/lib/workers/worker/index.js';
|
|
7
|
-
import { TestContext } from '../helpers/index.js';
|
|
8
|
-
describe('Worker', () => {
|
|
9
|
-
async function setupTest(options = {}) {
|
|
10
|
-
const slicerPort = await findPort();
|
|
11
|
-
options.slicerPort = slicerPort;
|
|
12
|
-
const testContext = new TestContext(options);
|
|
13
|
-
await testContext.initialize();
|
|
14
|
-
const server = new ExecutionController.Server({
|
|
15
|
-
port: slicerPort,
|
|
16
|
-
networkLatencyBuffer: 0,
|
|
17
|
-
actionTimeout: 1000,
|
|
18
|
-
workerDisconnectTimeout: 3000
|
|
19
|
-
});
|
|
20
|
-
testContext.attachCleanup(() => server.shutdown());
|
|
21
|
-
await server.start();
|
|
22
|
-
const worker = new Worker(testContext.context, testContext.executionContext);
|
|
23
|
-
testContext.attachCleanup(() => worker.shutdown());
|
|
24
|
-
return { server, worker, testContext };
|
|
25
|
-
}
|
|
26
|
-
describe('when running forever', () => {
|
|
27
|
-
let sliceConfig;
|
|
28
|
-
let worker;
|
|
29
|
-
let testContext;
|
|
30
|
-
let server;
|
|
31
|
-
let sliceSuccess;
|
|
32
|
-
let sliceFailure;
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
({ worker, testContext, server } = await setupTest());
|
|
35
|
-
await worker.initialize();
|
|
36
|
-
sliceConfig = await testContext.newSlice();
|
|
37
|
-
server.onClientAvailable(() => {
|
|
38
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
39
|
-
});
|
|
40
|
-
let shutdownPromise;
|
|
41
|
-
server.onSliceSuccess((workerId, _msg) => {
|
|
42
|
-
sliceSuccess = _msg;
|
|
43
|
-
shutdownPromise = worker.shutdown();
|
|
44
|
-
});
|
|
45
|
-
server.onSliceFailure((workerId, _msg) => {
|
|
46
|
-
sliceFailure = _msg;
|
|
47
|
-
shutdownPromise = worker.shutdown();
|
|
48
|
-
});
|
|
49
|
-
await worker.run();
|
|
50
|
-
await shutdownPromise;
|
|
51
|
-
});
|
|
52
|
-
afterEach(async () => {
|
|
53
|
-
await testContext.cleanup();
|
|
54
|
-
});
|
|
55
|
-
it('should complete the slice', () => {
|
|
56
|
-
expect(sliceFailure).toBeNil();
|
|
57
|
-
expect(sliceSuccess).toMatchObject({
|
|
58
|
-
slice: sliceConfig
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
describe('when running and the execution controller disconnects', () => {
|
|
63
|
-
let sliceConfig;
|
|
64
|
-
let worker;
|
|
65
|
-
let testContext;
|
|
66
|
-
let server;
|
|
67
|
-
let sliceSuccess;
|
|
68
|
-
let sliceFailure;
|
|
69
|
-
beforeEach(async () => {
|
|
70
|
-
({ worker, testContext, server } = await setupTest());
|
|
71
|
-
await worker.initialize();
|
|
72
|
-
sliceConfig = await testContext.newSlice();
|
|
73
|
-
server.onClientAvailable(() => {
|
|
74
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
75
|
-
});
|
|
76
|
-
let shutdownPromise;
|
|
77
|
-
server.onSliceSuccess((workerId, _msg) => {
|
|
78
|
-
sliceSuccess = _msg;
|
|
79
|
-
setTimeout(async () => {
|
|
80
|
-
shutdownPromise = server.shutdown();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
server.onSliceFailure((workerId, _msg) => {
|
|
84
|
-
sliceFailure = _msg;
|
|
85
|
-
setTimeout(async () => {
|
|
86
|
-
shutdownPromise = server.shutdown();
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
await worker.run();
|
|
90
|
-
await shutdownPromise;
|
|
91
|
-
});
|
|
92
|
-
afterEach(async () => {
|
|
93
|
-
await testContext.cleanup();
|
|
94
|
-
});
|
|
95
|
-
it('should complete the slice', () => {
|
|
96
|
-
expect(sliceFailure).toBeNil();
|
|
97
|
-
expect(sliceSuccess).toMatchObject({
|
|
98
|
-
slice: sliceConfig
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
describe('when a slice is sent from the execution controller', () => {
|
|
103
|
-
let sliceConfig;
|
|
104
|
-
let worker;
|
|
105
|
-
let testContext;
|
|
106
|
-
let server;
|
|
107
|
-
let sliceSuccess;
|
|
108
|
-
let sliceFailure;
|
|
109
|
-
beforeEach(async () => {
|
|
110
|
-
({ worker, testContext, server } = await setupTest());
|
|
111
|
-
await worker.initialize();
|
|
112
|
-
sliceConfig = await testContext.newSlice();
|
|
113
|
-
server.onClientAvailable(() => {
|
|
114
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
115
|
-
});
|
|
116
|
-
server.onSliceSuccess((workerId, _msg) => {
|
|
117
|
-
sliceSuccess = _msg;
|
|
118
|
-
});
|
|
119
|
-
server.onSliceFailure((workerId, _msg) => {
|
|
120
|
-
sliceFailure = _msg;
|
|
121
|
-
});
|
|
122
|
-
await worker.runOnce();
|
|
123
|
-
// avoid on slice events don't fire immediatley now
|
|
124
|
-
await pDelay(0);
|
|
125
|
-
});
|
|
126
|
-
afterEach(async () => {
|
|
127
|
-
await testContext.cleanup();
|
|
128
|
-
});
|
|
129
|
-
it('should complete the slice', () => {
|
|
130
|
-
expect(sliceFailure).toBeNil();
|
|
131
|
-
expect(sliceSuccess).toMatchObject({
|
|
132
|
-
slice: sliceConfig
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
describe('when a new slice is not sent right away', () => {
|
|
137
|
-
let msg;
|
|
138
|
-
let sliceConfig;
|
|
139
|
-
let worker;
|
|
140
|
-
let testContext;
|
|
141
|
-
let server;
|
|
142
|
-
let sliceFailure;
|
|
143
|
-
let sliceSuccess;
|
|
144
|
-
beforeEach(async () => {
|
|
145
|
-
({ worker, testContext, server } = await setupTest());
|
|
146
|
-
await worker.initialize();
|
|
147
|
-
server.onSliceSuccess((workerId, _msg) => {
|
|
148
|
-
sliceSuccess = _msg;
|
|
149
|
-
});
|
|
150
|
-
server.onSliceFailure((workerId, _msg) => {
|
|
151
|
-
sliceFailure = _msg;
|
|
152
|
-
});
|
|
153
|
-
const msgPromise = server.onceWithTimeout('worker:enqueue');
|
|
154
|
-
const workerStart = worker.runOnce();
|
|
155
|
-
await pDelay(500);
|
|
156
|
-
sliceConfig = await testContext.newSlice();
|
|
157
|
-
await server.dispatchSlice(sliceConfig, worker.workerId);
|
|
158
|
-
await workerStart;
|
|
159
|
-
msg = await msgPromise;
|
|
160
|
-
await pDelay(100);
|
|
161
|
-
});
|
|
162
|
-
afterEach(async () => {
|
|
163
|
-
await testContext.cleanup();
|
|
164
|
-
});
|
|
165
|
-
it('should re-enqueue the worker after receiving the slice complete message', () => {
|
|
166
|
-
expect(msg).not.toBeNil();
|
|
167
|
-
expect(sliceSuccess).toMatchObject({
|
|
168
|
-
slice: sliceConfig
|
|
169
|
-
});
|
|
170
|
-
expect(sliceFailure).toBeNil();
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
describe('when a slice errors', () => {
|
|
174
|
-
let worker;
|
|
175
|
-
let testContext;
|
|
176
|
-
let server;
|
|
177
|
-
let sliceFailure;
|
|
178
|
-
let sliceSuccess;
|
|
179
|
-
let msg;
|
|
180
|
-
beforeEach(async () => {
|
|
181
|
-
({ worker, testContext, server } = await setupTest());
|
|
182
|
-
await worker.initialize();
|
|
183
|
-
const operations = worker.executionContext.getOperations();
|
|
184
|
-
for (const op of operations) {
|
|
185
|
-
// @ts-expect-error
|
|
186
|
-
op.handle = jest.fn().mockRejectedValue(new Error('Bad news bears'));
|
|
187
|
-
}
|
|
188
|
-
server.onSliceSuccess((workerId, _msg) => {
|
|
189
|
-
sliceSuccess = _msg;
|
|
190
|
-
});
|
|
191
|
-
server.onSliceFailure((workerId, _msg) => {
|
|
192
|
-
sliceFailure = _msg;
|
|
193
|
-
});
|
|
194
|
-
const msgPromise = server.onceWithTimeout('worker:enqueue');
|
|
195
|
-
const sliceConfig = await testContext.newSlice();
|
|
196
|
-
server.onClientAvailable(() => {
|
|
197
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
198
|
-
});
|
|
199
|
-
await worker.runOnce();
|
|
200
|
-
msg = await msgPromise;
|
|
201
|
-
await pDelay(100);
|
|
202
|
-
});
|
|
203
|
-
afterEach(() => testContext.cleanup());
|
|
204
|
-
it('should return send a slice completed message with an error', () => {
|
|
205
|
-
expect(sliceSuccess).not.toBeObject();
|
|
206
|
-
const errMsg = 'TSError: Slice failed processing, caused by TSError: Bad news bears';
|
|
207
|
-
expect(sliceFailure).toBeObject();
|
|
208
|
-
expect(sliceFailure.error).toStartWith(errMsg);
|
|
209
|
-
expect(msg).not.toBeNil();
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
describe('when a slice is in-progress and shutdown is called', () => {
|
|
213
|
-
let workerShutdownEvent;
|
|
214
|
-
let worker;
|
|
215
|
-
let testContext;
|
|
216
|
-
let server;
|
|
217
|
-
beforeEach(async () => {
|
|
218
|
-
({ worker, testContext, server } = await setupTest());
|
|
219
|
-
await worker.initialize();
|
|
220
|
-
workerShutdownEvent = jest.fn();
|
|
221
|
-
worker.events.once('worker:shutdown', workerShutdownEvent);
|
|
222
|
-
worker.context.sysconfig.teraslice.shutdown_timeout = 1000;
|
|
223
|
-
// @ts-expect-error
|
|
224
|
-
worker.shutdownTimeout = 1000;
|
|
225
|
-
// @ts-expect-error
|
|
226
|
-
worker.slice.run = jest.fn(async () => pDelay(500));
|
|
227
|
-
const sliceConfig = await testContext.newSlice();
|
|
228
|
-
server.onClientAvailable(() => {
|
|
229
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
afterEach(async () => {
|
|
233
|
-
await testContext.cleanup();
|
|
234
|
-
});
|
|
235
|
-
it('should not have a shutdown err', async () => {
|
|
236
|
-
const promise = server.sendExecutionFinishedToAll(testContext.exId);
|
|
237
|
-
await expect(worker.shutdown()).resolves.toBeNil();
|
|
238
|
-
expect(workerShutdownEvent).toHaveBeenCalled();
|
|
239
|
-
await promise;
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
describe('when a slice is in-progress and has to be forced to shutdown', () => {
|
|
243
|
-
let shutdownErr;
|
|
244
|
-
let worker;
|
|
245
|
-
let testContext;
|
|
246
|
-
let server;
|
|
247
|
-
beforeEach(async () => {
|
|
248
|
-
({ worker, testContext, server } = await setupTest());
|
|
249
|
-
await worker.initialize();
|
|
250
|
-
worker.context.sysconfig.teraslice.shutdown_timeout = 500;
|
|
251
|
-
// @ts-expect-error
|
|
252
|
-
worker.shutdownTimeout = 500;
|
|
253
|
-
// @ts-expect-error
|
|
254
|
-
worker.slice.run = jest.fn(() => pDelay(1000));
|
|
255
|
-
const sliceConfig = await testContext.newSlice();
|
|
256
|
-
server.onClientAvailable(() => {
|
|
257
|
-
server.dispatchSlice(sliceConfig, worker.workerId);
|
|
258
|
-
});
|
|
259
|
-
let shutdown;
|
|
260
|
-
worker.events.once('slice:initialize', () => {
|
|
261
|
-
shutdown = worker.shutdown().catch((err) => {
|
|
262
|
-
shutdownErr = err;
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
await worker.run();
|
|
266
|
-
await shutdown;
|
|
267
|
-
});
|
|
268
|
-
afterEach(() => testContext.cleanup());
|
|
269
|
-
it('shutdown should throw an error', () => {
|
|
270
|
-
const errMsg = 'Error: Failed to shutdown correctly: Error: Worker shutdown timeout after 0.5 seconds, forcing shutdown';
|
|
271
|
-
expect(shutdownErr).not.toBeNil();
|
|
272
|
-
expect(shutdownErr.toString()).toStartWith(errMsg);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
describe('when constructed without nothing', () => {
|
|
276
|
-
it('should throw an error', () => {
|
|
277
|
-
expect(() => {
|
|
278
|
-
// @ts-expect-error
|
|
279
|
-
new Worker();
|
|
280
|
-
}).toThrow();
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
describe('when testing shutdown', () => {
|
|
284
|
-
let testContext;
|
|
285
|
-
let worker;
|
|
286
|
-
beforeEach(async () => {
|
|
287
|
-
testContext = new TestContext();
|
|
288
|
-
await testContext.initialize();
|
|
289
|
-
worker = new Worker(testContext.context, testContext.executionContext);
|
|
290
|
-
});
|
|
291
|
-
afterEach(() => testContext.cleanup());
|
|
292
|
-
describe('when not initialized', () => {
|
|
293
|
-
it('should resolve', () => expect(worker.shutdown()).resolves.toBeNil());
|
|
294
|
-
});
|
|
295
|
-
describe('when initialized', () => {
|
|
296
|
-
beforeEach(() => {
|
|
297
|
-
worker.isInitialized = true;
|
|
298
|
-
});
|
|
299
|
-
describe('when controller is already being shutdown', () => {
|
|
300
|
-
beforeEach(() => {
|
|
301
|
-
worker.isShuttingDown = true;
|
|
302
|
-
});
|
|
303
|
-
it('should resolve when shutdown passes', async () => {
|
|
304
|
-
setTimeout(() => {
|
|
305
|
-
worker.events.emit('worker:shutdown:complete');
|
|
306
|
-
});
|
|
307
|
-
await expect(worker.shutdown()).resolves.toBeNil();
|
|
308
|
-
});
|
|
309
|
-
it('should reject when shutdown fails', async () => {
|
|
310
|
-
setTimeout(() => {
|
|
311
|
-
worker.events.emit('worker:shutdown:complete', new Error('Uh oh'));
|
|
312
|
-
});
|
|
313
|
-
await expect(worker.shutdown()).rejects.toThrow('Uh oh');
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
describe('when everything errors', () => {
|
|
317
|
-
beforeEach(() => {
|
|
318
|
-
worker._waitForSliceToFinish = () => Promise.reject(new Error('Slice Finish Error'));
|
|
319
|
-
// @ts-expect-error
|
|
320
|
-
worker.stateStorage = {
|
|
321
|
-
shutdown: () => Promise.reject(new Error('Store Error'))
|
|
322
|
-
};
|
|
323
|
-
worker.analyticsStorage = {
|
|
324
|
-
// @ts-expect-error
|
|
325
|
-
shutdown: async () => Promise.resolve(true)
|
|
326
|
-
};
|
|
327
|
-
// @ts-expect-error
|
|
328
|
-
worker.slice = {
|
|
329
|
-
flush: () => Promise.reject(new Error('Flush Error')),
|
|
330
|
-
shutdown: () => Promise.reject(new Error('Slice Error'))
|
|
331
|
-
};
|
|
332
|
-
// @ts-expect-error
|
|
333
|
-
worker.client = {
|
|
334
|
-
shutdown: () => Promise.reject(new Error('Messenger Error'))
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
it('should reject with all of the errors', async () => {
|
|
338
|
-
expect.hasAssertions();
|
|
339
|
-
try {
|
|
340
|
-
await worker.shutdown();
|
|
341
|
-
}
|
|
342
|
-
catch (err) {
|
|
343
|
-
const errMsg = err.toString();
|
|
344
|
-
expect(errMsg).toStartWith('Error: Failed to shutdown correctly');
|
|
345
|
-
expect(errMsg).toInclude('Slice Finish Error');
|
|
346
|
-
expect(errMsg).toInclude('Store Error');
|
|
347
|
-
expect(errMsg).toInclude('Flush Error');
|
|
348
|
-
expect(errMsg).toInclude('Slice Error');
|
|
349
|
-
expect(errMsg).toInclude('Messenger Error');
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
//# sourceMappingURL=worker-spec.js.map
|