@emartech/program-executor 3.11.1 → 3.12.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/.env.example +9 -1
- package/.github/CODEOWNERS +1 -1
- package/.github/dependabot.yml +0 -7
- package/.github/workflows/main.yaml +17 -5
- package/docker-compose.yml +11 -0
- package/eslint.config.js +1 -5
- package/jest.config.js +13 -0
- package/package.json +12 -16
- package/src/create-test-databases.js +84 -0
- package/src/execution-time-exceeded-error/{index.spec.js → index.test.js} +3 -3
- package/src/graphql/{schema.spec.js → schema.test.js} +53 -24
- package/src/ignorable-error/{index.spec.js → index.test.js} +5 -5
- package/src/index-pubsub-e2e.test.js +209 -0
- package/src/index-pubsub.js +84 -0
- package/src/index-pubsub.test.js +160 -0
- package/src/{index.spec.js → index.test.js} +42 -38
- package/src/job-data-handler/{index.spec.js → index.test.js} +15 -21
- package/src/program-executor-processor/{index.spec.js → index.test.js} +59 -48
- package/src/program-handler/{index.spec.js → index.test.js} +58 -34
- package/src/queue-manager/{index.spec.js → index.test.js} +16 -19
- package/src/queue-manager-pubsub/index.js +33 -0
- package/src/queue-manager-pubsub/index.test.js +44 -0
- package/src/repositories/{programs.spec.js → programs.test.js} +54 -37
- package/src/retryable-error/{index.spec.js → index.test.js} +5 -5
- package/src/runid-generator/{index.spec.js → index.test.js} +2 -2
- package/src/test-helper/get-test-db-config.js +29 -0
- package/src/testSetup.js +23 -0
- package/src/testTeardown.js +13 -0
- package/src/setup.spec.js +0 -50
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const JobHandler = require('
|
|
3
|
+
const JobHandler = require('.');
|
|
4
4
|
const ExecutionTimeExceededError = require('../execution-time-exceeded-error');
|
|
5
|
+
jest.useFakeTimers();
|
|
5
6
|
|
|
6
7
|
describe('JobDataHandler', function () {
|
|
7
8
|
let programHandlerStub;
|
|
8
9
|
|
|
9
10
|
beforeEach(function () {
|
|
10
11
|
programHandlerStub = {
|
|
11
|
-
getJobData:
|
|
12
|
-
updateJobData:
|
|
12
|
+
getJobData: jest.fn().mockResolvedValue(true),
|
|
13
|
+
updateJobData: jest.fn().mockResolvedValue(true)
|
|
13
14
|
};
|
|
14
15
|
});
|
|
15
16
|
|
|
@@ -20,7 +21,7 @@ describe('JobDataHandler', function () {
|
|
|
20
21
|
|
|
21
22
|
await JobHandler.create(programHandlerStub, runId, program).get();
|
|
22
23
|
|
|
23
|
-
expect(programHandlerStub.getJobData).
|
|
24
|
+
expect(programHandlerStub.getJobData).toHaveBeenCalledWith(runId, program);
|
|
24
25
|
});
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -31,7 +32,7 @@ describe('JobDataHandler', function () {
|
|
|
31
32
|
|
|
32
33
|
await JobHandler.create(programHandlerStub, runId, program).set({ test: 'data' });
|
|
33
34
|
|
|
34
|
-
expect(programHandlerStub.updateJobData).
|
|
35
|
+
expect(programHandlerStub.updateJobData).toHaveBeenCalledWith(runId, program, { test: 'data' });
|
|
35
36
|
});
|
|
36
37
|
});
|
|
37
38
|
|
|
@@ -42,7 +43,7 @@ describe('JobDataHandler', function () {
|
|
|
42
43
|
|
|
43
44
|
await JobHandler.create(programHandlerStub, runId, program).merge({ test: 'data' });
|
|
44
45
|
|
|
45
|
-
expect(programHandlerStub.updateJobData).
|
|
46
|
+
expect(programHandlerStub.updateJobData).toHaveBeenCalledWith(runId, program, { test: 'data' }, true);
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
49
|
|
|
@@ -53,18 +54,17 @@ describe('JobDataHandler', function () {
|
|
|
53
54
|
|
|
54
55
|
await JobHandler.create(programHandlerStub, runId, program).checkpoint({ test: 'data' });
|
|
55
56
|
|
|
56
|
-
expect(programHandlerStub.updateJobData).
|
|
57
|
+
expect(programHandlerStub.updateJobData).toHaveBeenCalledWith(runId, program, { test: 'data' }, true);
|
|
57
58
|
});
|
|
58
59
|
|
|
59
60
|
it('should throw an ExecutionTimeExceededError if execution takes longer than given duration', async function () {
|
|
60
|
-
const clock = this.sandbox.useFakeTimers();
|
|
61
61
|
const runId = '1';
|
|
62
62
|
const program = 'product_sync';
|
|
63
63
|
const maxExecutionTime = 1000;
|
|
64
64
|
|
|
65
65
|
const jobHandler = JobHandler.create(programHandlerStub, runId, program);
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
jest.advanceTimersByTime(maxExecutionTime + 1);
|
|
68
68
|
|
|
69
69
|
let expectedError;
|
|
70
70
|
try {
|
|
@@ -73,20 +73,17 @@ describe('JobDataHandler', function () {
|
|
|
73
73
|
expectedError = error;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
expect(expectedError).
|
|
77
|
-
expect(expectedError.executionTimeExceeded).
|
|
78
|
-
clock.restore();
|
|
76
|
+
expect(expectedError).toBeInstanceOf(ExecutionTimeExceededError);
|
|
77
|
+
expect(expectedError.executionTimeExceeded).toBe(true);
|
|
79
78
|
});
|
|
80
79
|
|
|
81
80
|
it('should not throw an exception if execution time is shorter than given duration', async function () {
|
|
82
|
-
const clock = this.sandbox.useFakeTimers();
|
|
83
81
|
const runId = '1';
|
|
84
82
|
const program = 'product_sync';
|
|
85
83
|
const maxExecutionTime = 1000;
|
|
86
84
|
|
|
87
85
|
const jobHandler = JobHandler.create(programHandlerStub, runId, program);
|
|
88
|
-
|
|
89
|
-
clock.tick(maxExecutionTime - 1);
|
|
86
|
+
jest.advanceTimersByTime(maxExecutionTime - 1);
|
|
90
87
|
|
|
91
88
|
let expectedError;
|
|
92
89
|
try {
|
|
@@ -95,19 +92,17 @@ describe('JobDataHandler', function () {
|
|
|
95
92
|
expectedError = error;
|
|
96
93
|
}
|
|
97
94
|
|
|
98
|
-
expect(expectedError).
|
|
99
|
-
clock.restore();
|
|
95
|
+
expect(expectedError).toBe(undefined);
|
|
100
96
|
});
|
|
101
97
|
|
|
102
98
|
[0, null, undefined].forEach((executionTime) => {
|
|
103
99
|
it('should not throw an exception if no max execution time given', async function () {
|
|
104
|
-
const clock = this.sandbox.useFakeTimers();
|
|
105
100
|
const runId = '1';
|
|
106
101
|
const program = 'product_sync';
|
|
107
102
|
|
|
108
103
|
const jobHandler = JobHandler.create(programHandlerStub, runId, program);
|
|
109
104
|
|
|
110
|
-
|
|
105
|
+
jest.advanceTimersByTime(99999);
|
|
111
106
|
|
|
112
107
|
let expectedError;
|
|
113
108
|
try {
|
|
@@ -116,8 +111,7 @@ describe('JobDataHandler', function () {
|
|
|
116
111
|
expectedError = error;
|
|
117
112
|
}
|
|
118
113
|
|
|
119
|
-
expect(expectedError).
|
|
120
|
-
clock.restore();
|
|
114
|
+
expect(expectedError).toBe(undefined);
|
|
121
115
|
});
|
|
122
116
|
});
|
|
123
117
|
});
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ProgramExecutorProcessor = require('
|
|
3
|
+
const ProgramExecutorProcessor = require('.');
|
|
4
4
|
|
|
5
5
|
const ProgramHandler = require('../program-handler');
|
|
6
6
|
const JobDataHandler = require('../job-data-handler');
|
|
7
7
|
const QueueManager = require('../queue-manager');
|
|
8
|
+
const JobHandler = require('../job-data-handler');
|
|
9
|
+
|
|
10
|
+
jest.mock('../job-data-handler');
|
|
8
11
|
|
|
9
12
|
describe('ProgramExecutorProcessor', function () {
|
|
10
13
|
let programHandler;
|
|
@@ -16,6 +19,9 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
16
19
|
let failingJobExecuteWithIgnorableErrorStub;
|
|
17
20
|
let failingJobExecuteWithRetryableErrorStub;
|
|
18
21
|
let programHandlerIsProgramFinishedWithErrorStub;
|
|
22
|
+
let mockProgramHandler;
|
|
23
|
+
let setProgramToErrorStub;
|
|
24
|
+
let mockQueueProgram;
|
|
19
25
|
|
|
20
26
|
beforeEach(async function () {
|
|
21
27
|
const ignorableError = new Error('Something wrong happened, but ignore this!');
|
|
@@ -25,56 +31,63 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
25
31
|
const executionTimeExceededError = new Error('Timeout exceeded, but please retry!');
|
|
26
32
|
executionTimeExceededError.executionTimeExceeded = true;
|
|
27
33
|
|
|
28
|
-
testJobExecuteStub =
|
|
29
|
-
failingJobExecuteStub =
|
|
30
|
-
failingJobExecuteWithIgnorableErrorStub =
|
|
31
|
-
failingJobExecuteWithRetryableErrorStub =
|
|
34
|
+
testJobExecuteStub = jest.fn();
|
|
35
|
+
failingJobExecuteStub = jest.fn().mockRejectedValue(new Error('Something wrong happened!'));
|
|
36
|
+
failingJobExecuteWithIgnorableErrorStub = jest.fn().mockRejectedValue(ignorableError);
|
|
37
|
+
failingJobExecuteWithRetryableErrorStub = jest.fn().mockRejectedValue(retryableError);
|
|
32
38
|
jobLibrary = {
|
|
33
39
|
testJob: {
|
|
34
|
-
create:
|
|
40
|
+
create: jest.fn().mockReturnValue({
|
|
35
41
|
execute: testJobExecuteStub
|
|
36
42
|
})
|
|
37
43
|
},
|
|
38
44
|
currentJob: {
|
|
39
|
-
create:
|
|
45
|
+
create: jest.fn().mockReturnValue({ execute() {} })
|
|
40
46
|
},
|
|
41
47
|
nextJob: {
|
|
42
|
-
create:
|
|
48
|
+
create: jest.fn().mockReturnValue({ execute() {} })
|
|
43
49
|
},
|
|
44
50
|
failingJob: {
|
|
45
|
-
create:
|
|
51
|
+
create: jest.fn().mockReturnValue({
|
|
46
52
|
execute: failingJobExecuteStub
|
|
47
53
|
})
|
|
48
54
|
},
|
|
49
55
|
failingJobWithIgnorableError: {
|
|
50
|
-
create:
|
|
56
|
+
create: jest.fn().mockReturnValue({
|
|
51
57
|
execute: failingJobExecuteWithIgnorableErrorStub
|
|
52
58
|
})
|
|
53
59
|
},
|
|
54
60
|
failingJobWithRetryableError: {
|
|
55
|
-
create:
|
|
61
|
+
create: jest.fn().mockReturnValue({
|
|
56
62
|
execute: failingJobExecuteWithRetryableErrorStub
|
|
57
63
|
})
|
|
58
64
|
},
|
|
59
65
|
failingJobWithExecutionTimeExceededError: {
|
|
60
|
-
create:
|
|
61
|
-
execute:
|
|
66
|
+
create: jest.fn().mockReturnValue({
|
|
67
|
+
execute: jest.fn().mockRejectedValue(executionTimeExceededError)
|
|
62
68
|
})
|
|
63
69
|
}
|
|
64
70
|
};
|
|
71
|
+
mockQueueProgram = jest.fn().mockResolvedValue(true);
|
|
72
|
+
programHandlerIsProgramFinishedWithErrorStub = jest.fn().mockResolvedValue(false);
|
|
73
|
+
setProgramToErrorStub = jest.fn().mockResolvedValue(true);
|
|
74
|
+
|
|
75
|
+
mockProgramHandler = {
|
|
76
|
+
finishProgram: jest.fn().mockResolvedValue(true),
|
|
77
|
+
setProgramToError: jest.fn().mockResolvedValue(true),
|
|
78
|
+
setJobRetriableErrorMessage: jest.fn().mockResolvedValue(true),
|
|
79
|
+
incrementStep: jest.fn().mockResolvedValue(true),
|
|
80
|
+
incrementStepRetryCount: jest.fn().mockResolvedValue(true),
|
|
81
|
+
isProgramFinishedWithError: programHandlerIsProgramFinishedWithErrorStub,
|
|
82
|
+
setProgramToError: setProgramToErrorStub
|
|
83
|
+
};
|
|
84
|
+
ProgramHandler.create = jest.fn().mockReturnValue(mockProgramHandler);
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.sandbox.stub(ProgramHandler.prototype, 'setJobRetriableErrorMessage').resolves(true);
|
|
70
|
-
this.sandbox.stub(ProgramHandler.prototype, 'incrementStep').resolves(true);
|
|
71
|
-
this.sandbox.stub(ProgramHandler.prototype, 'incrementStepRetryCount').resolves(true);
|
|
72
|
-
programHandlerIsProgramFinishedWithErrorStub = this.sandbox
|
|
73
|
-
.stub(ProgramHandler.prototype, 'isProgramFinishedWithError')
|
|
74
|
-
.resolves(false);
|
|
75
|
-
|
|
76
|
-
this.sandbox.stub(QueueManager.prototype, 'queueProgram').resolves(true);
|
|
86
|
+
QueueManager.create = jest.fn().mockReturnValue({
|
|
87
|
+
queueProgram: mockQueueProgram
|
|
88
|
+
});
|
|
77
89
|
|
|
90
|
+
JobHandler.create = jest.fn().mockReturnValue(new JobHandler());
|
|
78
91
|
programHandler = ProgramHandler.create();
|
|
79
92
|
queueManager = QueueManager.create();
|
|
80
93
|
});
|
|
@@ -92,12 +105,12 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
92
105
|
runId: '1'
|
|
93
106
|
});
|
|
94
107
|
|
|
95
|
-
expect(jobLibrary.testJob.create).
|
|
96
|
-
expect(testJobExecuteStub).
|
|
108
|
+
expect(jobLibrary.testJob.create).toHaveBeenCalledWith(programData);
|
|
109
|
+
expect(testJobExecuteStub).toHaveBeenCalledWith(({
|
|
97
110
|
programData,
|
|
98
111
|
jobs: ['testJob'],
|
|
99
112
|
runId: '1'
|
|
100
|
-
});
|
|
113
|
+
}), expect.any(JobDataHandler));
|
|
101
114
|
});
|
|
102
115
|
|
|
103
116
|
it('should pass job data handler for the given job and runId pair', async function () {
|
|
@@ -107,22 +120,20 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
107
120
|
runId: '1'
|
|
108
121
|
});
|
|
109
122
|
|
|
110
|
-
const jobDataHandler = testJobExecuteStub.
|
|
111
|
-
|
|
112
|
-
expect(JobDataHandler.create).to.be.calledWith(this.sinon.match.instanceOf(ProgramHandler), '1', 'testJob');
|
|
113
|
-
expect(jobDataHandler).to.be.an.instanceOf(JobDataHandler);
|
|
123
|
+
const jobDataHandler = testJobExecuteStub.mock.calls[0][1];
|
|
124
|
+
expect(jobDataHandler).toBeInstanceOf(JobDataHandler);
|
|
114
125
|
});
|
|
115
126
|
|
|
116
127
|
it('should cancel execution if program already encountered an error', async function () {
|
|
117
|
-
programHandlerIsProgramFinishedWithErrorStub.
|
|
128
|
+
programHandlerIsProgramFinishedWithErrorStub.mockResolvedValue(true)(true);
|
|
118
129
|
await ProgramExecutorProcessor.create(programHandler, queueManager, jobLibrary).process({
|
|
119
130
|
jobs: ['testJob'],
|
|
120
131
|
programData: {},
|
|
121
132
|
runId: '1'
|
|
122
133
|
});
|
|
123
134
|
|
|
124
|
-
expect(testJobExecuteStub).not.
|
|
125
|
-
expect(
|
|
135
|
+
expect(testJobExecuteStub).not.toHaveBeenCalled();
|
|
136
|
+
expect(mockQueueProgram).not.toHaveBeenCalled();
|
|
126
137
|
});
|
|
127
138
|
|
|
128
139
|
it('should throw an error if a job fails with non-ignorable error', async function () {
|
|
@@ -137,8 +148,8 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
137
148
|
caughtError = error;
|
|
138
149
|
}
|
|
139
150
|
|
|
140
|
-
expect(caughtError).not.
|
|
141
|
-
expect(failingJobExecuteStub).
|
|
151
|
+
expect(caughtError).not.toBe(undefined);
|
|
152
|
+
expect(failingJobExecuteStub).toHaveBeenCalled();
|
|
142
153
|
});
|
|
143
154
|
|
|
144
155
|
it('should throw a retryable error if a job fails with ExecutionTimeExceededError', async function () {
|
|
@@ -153,7 +164,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
153
164
|
caughtError = error;
|
|
154
165
|
}
|
|
155
166
|
|
|
156
|
-
expect(caughtError.retryable).
|
|
167
|
+
expect(caughtError.retryable).toBe(true);
|
|
157
168
|
});
|
|
158
169
|
|
|
159
170
|
it('should not throw an error if a job fails with an ignorable error', async function () {
|
|
@@ -162,7 +173,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
162
173
|
programData: {},
|
|
163
174
|
runId: '1'
|
|
164
175
|
});
|
|
165
|
-
expect(
|
|
176
|
+
expect(mockProgramHandler.setProgramToError).toHaveBeenCalledWith(
|
|
166
177
|
'1',
|
|
167
178
|
'Something wrong happened, but ignore this!'
|
|
168
179
|
);
|
|
@@ -177,8 +188,8 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
177
188
|
});
|
|
178
189
|
// eslint-disable-next-line no-unused-vars
|
|
179
190
|
} catch (error) {
|
|
180
|
-
expect(
|
|
181
|
-
expect(
|
|
191
|
+
expect(mockProgramHandler.setProgramToError).toHaveBeenCalledWith('1', 'Something wrong happened!');
|
|
192
|
+
expect(mockProgramHandler.setJobRetriableErrorMessage).not.toHaveBeenCalled();
|
|
182
193
|
}
|
|
183
194
|
});
|
|
184
195
|
|
|
@@ -192,7 +203,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
192
203
|
// eslint-disable-next-line no-empty, no-unused-vars
|
|
193
204
|
} catch (_error) {}
|
|
194
205
|
|
|
195
|
-
expect(
|
|
206
|
+
expect(mockProgramHandler.incrementStepRetryCount).toHaveBeenCalledWith('1');
|
|
196
207
|
});
|
|
197
208
|
|
|
198
209
|
it('should update error message only if job fails with retriable error', async function () {
|
|
@@ -204,8 +215,8 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
204
215
|
});
|
|
205
216
|
// eslint-disable-next-line no-unused-vars
|
|
206
217
|
} catch (error) {
|
|
207
|
-
expect(
|
|
208
|
-
expect(
|
|
218
|
+
expect(mockProgramHandler.setProgramToError).not.toHaveBeenCalled();
|
|
219
|
+
expect(mockProgramHandler.setJobRetriableErrorMessage).toHaveBeenCalledWith(
|
|
209
220
|
'1',
|
|
210
221
|
'Something wrong happened, but please retry!'
|
|
211
222
|
);
|
|
@@ -221,7 +232,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
221
232
|
}
|
|
222
233
|
});
|
|
223
234
|
|
|
224
|
-
expect(
|
|
235
|
+
expect(mockQueueProgram).toHaveBeenCalledWith({
|
|
225
236
|
jobs: ['nextJob'],
|
|
226
237
|
programData: {
|
|
227
238
|
customerId: 123,
|
|
@@ -237,7 +248,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
237
248
|
runId: '1'
|
|
238
249
|
});
|
|
239
250
|
|
|
240
|
-
expect(
|
|
251
|
+
expect(mockProgramHandler.incrementStep).toHaveBeenCalledWith('1');
|
|
241
252
|
});
|
|
242
253
|
|
|
243
254
|
it('should not requeue when it was the last job', async function () {
|
|
@@ -247,7 +258,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
247
258
|
runId: '1'
|
|
248
259
|
});
|
|
249
260
|
|
|
250
|
-
expect(
|
|
261
|
+
expect(mockQueueProgram).not.toHaveBeenCalled();
|
|
251
262
|
});
|
|
252
263
|
|
|
253
264
|
it('should set program to finished when it was the last job', async function () {
|
|
@@ -257,7 +268,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
257
268
|
runId: '1'
|
|
258
269
|
});
|
|
259
270
|
|
|
260
|
-
expect(
|
|
271
|
+
expect(mockProgramHandler.finishProgram).toHaveBeenCalledWith('1');
|
|
261
272
|
});
|
|
262
273
|
|
|
263
274
|
it('should not set job to finished when it was not the last job', async function () {
|
|
@@ -267,7 +278,7 @@ describe('ProgramExecutorProcessor', function () {
|
|
|
267
278
|
runId: '1'
|
|
268
279
|
});
|
|
269
280
|
|
|
270
|
-
expect(
|
|
281
|
+
expect(mockProgramHandler.finishProgram).not.toHaveBeenCalled();
|
|
271
282
|
});
|
|
272
283
|
});
|
|
273
284
|
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const ProgramHandler = require('
|
|
3
|
+
const ProgramHandler = require('.');
|
|
4
4
|
const QueueManager = require('../queue-manager');
|
|
5
5
|
const ProgramsRepository = require('../repositories/programs');
|
|
6
|
+
const knex = require('knex');
|
|
7
|
+
const DbCleaner = require('../test-helper/db-cleaner');
|
|
8
|
+
const { db } = require('../test-helper/get-test-db-config');
|
|
6
9
|
|
|
7
10
|
const hostname = 'yolo.myshopify.com';
|
|
8
11
|
const customerId = 123;
|
|
@@ -10,15 +13,36 @@ const customerId = 123;
|
|
|
10
13
|
describe('ProgramHandler', function () {
|
|
11
14
|
let programsRepository;
|
|
12
15
|
let queueManager;
|
|
13
|
-
let
|
|
16
|
+
let mockQueueProgram;
|
|
17
|
+
let dbConnection;
|
|
18
|
+
|
|
19
|
+
beforeAll(function () {
|
|
20
|
+
|
|
21
|
+
dbConnection = knex({
|
|
22
|
+
client: 'pg',
|
|
23
|
+
connection: db.connection.connString
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterAll(async function () {
|
|
28
|
+
await DbCleaner.create(dbConnection).tearDown();
|
|
29
|
+
dbConnection.destroy();
|
|
30
|
+
});
|
|
31
|
+
|
|
14
32
|
|
|
15
33
|
beforeEach(async function () {
|
|
16
|
-
|
|
34
|
+
await DbCleaner.create(dbConnection).tearDown();
|
|
35
|
+
mockQueueProgram = jest.fn().mockResolvedValue(true);
|
|
36
|
+
QueueManager.create = jest.fn().mockReturnValue({
|
|
37
|
+
queueProgram: mockQueueProgram
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
programsRepository = ProgramsRepository.create(dbConnection, 'programs');
|
|
17
42
|
queueManager = QueueManager.create('amqp://guest:guest@localhost:9999', 'program-executor');
|
|
18
|
-
queueProgramStub = this.sandbox.stub(QueueManager.prototype, 'queueProgram').resolves(true);
|
|
19
43
|
});
|
|
20
44
|
|
|
21
|
-
describe('#createProgram',
|
|
45
|
+
describe('#createProgram', function () {
|
|
22
46
|
it('should create a program with the given jobs and program data', async function () {
|
|
23
47
|
const programData = { test: 'data' };
|
|
24
48
|
|
|
@@ -27,10 +51,10 @@ describe('ProgramHandler', function () {
|
|
|
27
51
|
jobs: ['current_program', 'next_program']
|
|
28
52
|
});
|
|
29
53
|
|
|
30
|
-
expect(
|
|
54
|
+
expect(mockQueueProgram).toHaveBeenCalledWith(expect.objectContaining({
|
|
31
55
|
jobs: ['current_program', 'next_program'],
|
|
32
56
|
programData
|
|
33
|
-
});
|
|
57
|
+
}));
|
|
34
58
|
});
|
|
35
59
|
|
|
36
60
|
it('should save program in db', async function () {
|
|
@@ -39,7 +63,7 @@ describe('ProgramHandler', function () {
|
|
|
39
63
|
});
|
|
40
64
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
41
65
|
|
|
42
|
-
expect(program.jobs).
|
|
66
|
+
expect(program.jobs).toEqual(['current_program', 'next_program']);
|
|
43
67
|
});
|
|
44
68
|
|
|
45
69
|
it('should save program data in db', async function () {
|
|
@@ -53,7 +77,7 @@ describe('ProgramHandler', function () {
|
|
|
53
77
|
});
|
|
54
78
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
55
79
|
|
|
56
|
-
expect(program.programData).
|
|
80
|
+
expect(program.programData).toEqual({ hostname, customerId });
|
|
57
81
|
});
|
|
58
82
|
|
|
59
83
|
it('should save job data in db', async function () {
|
|
@@ -69,7 +93,7 @@ describe('ProgramHandler', function () {
|
|
|
69
93
|
});
|
|
70
94
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
71
95
|
|
|
72
|
-
expect(program.jobData).
|
|
96
|
+
expect(program.jobData).toEqual(jobData);
|
|
73
97
|
});
|
|
74
98
|
|
|
75
99
|
it('should generate a runid for the program', async function () {
|
|
@@ -77,7 +101,7 @@ describe('ProgramHandler', function () {
|
|
|
77
101
|
jobs: ['current_program', 'next_program']
|
|
78
102
|
});
|
|
79
103
|
|
|
80
|
-
expect(
|
|
104
|
+
expect(mockQueueProgram.mock.calls[0][0].runId).not.toBe(undefined);
|
|
81
105
|
});
|
|
82
106
|
|
|
83
107
|
it('should return the generated runid', async function () {
|
|
@@ -85,12 +109,12 @@ describe('ProgramHandler', function () {
|
|
|
85
109
|
jobs: ['current_program', 'next_program']
|
|
86
110
|
});
|
|
87
111
|
|
|
88
|
-
const generatedRunId =
|
|
89
|
-
expect(generatedRunId).
|
|
112
|
+
const generatedRunId = mockQueueProgram.mock.calls[0][0].runId;
|
|
113
|
+
expect(generatedRunId).toEqual(result);
|
|
90
114
|
});
|
|
91
115
|
});
|
|
92
116
|
|
|
93
|
-
describe('#finishProgram',
|
|
117
|
+
describe('#finishProgram', function () {
|
|
94
118
|
it('should set job to finished in db', async function () {
|
|
95
119
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
96
120
|
|
|
@@ -101,11 +125,11 @@ describe('ProgramHandler', function () {
|
|
|
101
125
|
await programHandler.finishProgram(runId);
|
|
102
126
|
|
|
103
127
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
104
|
-
expect(program.finishedAt).not.
|
|
128
|
+
expect(program.finishedAt).not.toBe(undefined);
|
|
105
129
|
});
|
|
106
130
|
});
|
|
107
131
|
|
|
108
|
-
describe('#getJobData',
|
|
132
|
+
describe('#getJobData', function () {
|
|
109
133
|
it('should get program data for runid and program name', async function () {
|
|
110
134
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
111
135
|
const runId = await programHandler.createProgram({
|
|
@@ -114,11 +138,11 @@ describe('ProgramHandler', function () {
|
|
|
114
138
|
await programHandler.updateJobData(runId, 'product_sync', { page: 123 });
|
|
115
139
|
|
|
116
140
|
const jobData = await programHandler.getJobData(runId, 'product_sync');
|
|
117
|
-
expect(jobData).
|
|
141
|
+
expect(jobData).toEqual({ page: 123 });
|
|
118
142
|
});
|
|
119
143
|
});
|
|
120
144
|
|
|
121
|
-
describe('#setProgramToError',
|
|
145
|
+
describe('#setProgramToError', function () {
|
|
122
146
|
it('should set job to errored in db', async function () {
|
|
123
147
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
124
148
|
|
|
@@ -128,12 +152,12 @@ describe('ProgramHandler', function () {
|
|
|
128
152
|
await programHandler.setProgramToError(runId, 'Something wrong happened!');
|
|
129
153
|
|
|
130
154
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
131
|
-
expect(program.erroredAt).not.
|
|
132
|
-
expect(program.errorMessage).
|
|
155
|
+
expect(program.erroredAt).not.toBe(undefined);
|
|
156
|
+
expect(program.errorMessage).toEqual('Something wrong happened!');
|
|
133
157
|
});
|
|
134
158
|
});
|
|
135
159
|
|
|
136
|
-
describe('#isProgramFinishedWithError',
|
|
160
|
+
describe('#isProgramFinishedWithError', function () {
|
|
137
161
|
it('should return true if erroredAt is not null', async function () {
|
|
138
162
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
139
163
|
|
|
@@ -143,7 +167,7 @@ describe('ProgramHandler', function () {
|
|
|
143
167
|
await programHandler.setProgramToError(runId, 'Something wrong happened!');
|
|
144
168
|
|
|
145
169
|
const result = await programHandler.isProgramFinishedWithError(runId);
|
|
146
|
-
expect(result).
|
|
170
|
+
expect(result).toBe(true);
|
|
147
171
|
});
|
|
148
172
|
|
|
149
173
|
it('should return false if erroredAt is null', async function () {
|
|
@@ -154,11 +178,11 @@ describe('ProgramHandler', function () {
|
|
|
154
178
|
});
|
|
155
179
|
|
|
156
180
|
const result = await programHandler.isProgramFinishedWithError(runId);
|
|
157
|
-
expect(result).
|
|
181
|
+
expect(result).toBe(false);
|
|
158
182
|
});
|
|
159
183
|
});
|
|
160
184
|
|
|
161
|
-
describe('#setJobRetriableErrorMessage',
|
|
185
|
+
describe('#setJobRetriableErrorMessage', function () {
|
|
162
186
|
it('should set program to errored in db', async function () {
|
|
163
187
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
164
188
|
|
|
@@ -168,13 +192,13 @@ describe('ProgramHandler', function () {
|
|
|
168
192
|
await programHandler.setJobRetriableErrorMessage(runId, 'Something wrong happened!');
|
|
169
193
|
|
|
170
194
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
171
|
-
expect(program.finishedAt).
|
|
172
|
-
expect(program.erroredAt).
|
|
173
|
-
expect(program.errorMessage).
|
|
195
|
+
expect(program.finishedAt).toEqual(null);
|
|
196
|
+
expect(program.erroredAt).toEqual(null);
|
|
197
|
+
expect(program.errorMessage).toEqual('Something wrong happened!');
|
|
174
198
|
});
|
|
175
199
|
});
|
|
176
200
|
|
|
177
|
-
describe('#incrementStep',
|
|
201
|
+
describe('#incrementStep', function () {
|
|
178
202
|
it('should increment step', async function () {
|
|
179
203
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
180
204
|
|
|
@@ -184,11 +208,11 @@ describe('ProgramHandler', function () {
|
|
|
184
208
|
await programHandler.incrementStep(runId);
|
|
185
209
|
|
|
186
210
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
187
|
-
expect(program.step).
|
|
211
|
+
expect(program.step).toEqual(1);
|
|
188
212
|
});
|
|
189
213
|
});
|
|
190
214
|
|
|
191
|
-
describe('#incrementStepRetryCount',
|
|
215
|
+
describe('#incrementStepRetryCount', function () {
|
|
192
216
|
it('should increment StepRetryCount', async function () {
|
|
193
217
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
194
218
|
|
|
@@ -198,11 +222,11 @@ describe('ProgramHandler', function () {
|
|
|
198
222
|
await programHandler.incrementStepRetryCount(runId);
|
|
199
223
|
|
|
200
224
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
201
|
-
expect(program.stepRetryCount).
|
|
225
|
+
expect(program.stepRetryCount).toEqual(1);
|
|
202
226
|
});
|
|
203
227
|
});
|
|
204
228
|
|
|
205
|
-
describe('#updateJobData',
|
|
229
|
+
describe('#updateJobData', function () {
|
|
206
230
|
it('should update job data related to jobName overwriting the full payload', async function () {
|
|
207
231
|
const programHandler = ProgramHandler.create(programsRepository, queueManager);
|
|
208
232
|
const runId = await programHandler.createProgram({
|
|
@@ -213,7 +237,7 @@ describe('ProgramHandler', function () {
|
|
|
213
237
|
await programHandler.updateJobData(runId, 'contact-sync', { page: 10 });
|
|
214
238
|
|
|
215
239
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
216
|
-
expect(program.jobData).
|
|
240
|
+
expect(program.jobData).toEqual({
|
|
217
241
|
'contact-sync': { page: 10 }
|
|
218
242
|
});
|
|
219
243
|
});
|
|
@@ -228,7 +252,7 @@ describe('ProgramHandler', function () {
|
|
|
228
252
|
await programHandler.updateJobData(runId, 'contact-sync', { page: 10 }, true);
|
|
229
253
|
|
|
230
254
|
const program = await programsRepository.getProgramByRunId(runId);
|
|
231
|
-
expect(program.jobData).
|
|
255
|
+
expect(program.jobData).toEqual({
|
|
232
256
|
'contact-sync': { this_wont_be_gone: ':)', page: 10 }
|
|
233
257
|
});
|
|
234
258
|
});
|