screwdriver-queue-service 2.0.34 → 2.0.37
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/lib/queue.js +3 -2
- package/package.json +2 -2
- package/plugins/helper.js +1 -1
- package/plugins/queue/scheduler.js +35 -25
- package/plugins/redis.js +29 -0
- package/plugins/worker/lib/BlockedBy.js +2 -3
- package/plugins/worker/lib/jobs.js +2 -4
- package/plugins/worker/worker.js +25 -24
package/lib/queue.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const Redis = require('ioredis');
|
|
4
3
|
const Resque = require('node-resque');
|
|
5
4
|
const fuses = require('circuit-fuses');
|
|
6
5
|
const Breaker = fuses.breaker;
|
|
7
6
|
const FuseBox = fuses.box;
|
|
8
7
|
const logger = require('screwdriver-logger');
|
|
8
|
+
const redis = require('../plugins/redis');
|
|
9
9
|
|
|
10
10
|
module.exports = class ExecutorQueue {
|
|
11
11
|
/**
|
|
@@ -41,10 +41,11 @@ module.exports = class ExecutorQueue {
|
|
|
41
41
|
|
|
42
42
|
this.redisConnection = redisConnection;
|
|
43
43
|
|
|
44
|
-
this.redis =
|
|
44
|
+
this.redis = redis;
|
|
45
45
|
|
|
46
46
|
// eslint-disable-next-line new-cap
|
|
47
47
|
this.queue = new Resque.Queue({ connection: redisConnection });
|
|
48
|
+
this.queue.on('error', error => logger.info(`Resque queue error >> ${error}`));
|
|
48
49
|
this.queueBreaker = new Breaker((funcName, ...args) => {
|
|
49
50
|
const callback = args.pop();
|
|
50
51
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "screwdriver-queue-service",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.37",
|
|
4
4
|
"description": "Screwdriver Queue Service API",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"directories": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"config": "^1.31.0",
|
|
21
21
|
"cron-parser": "^4.2.1",
|
|
22
22
|
"hapi-auth-jwt2": "^10.2.0",
|
|
23
|
-
"ioredis": "^
|
|
23
|
+
"ioredis": "^5.0.4",
|
|
24
24
|
"joi": "^17.5.0",
|
|
25
25
|
"js-yaml": "^3.14.1",
|
|
26
26
|
"jsonwebtoken": "^8.5.1",
|
package/plugins/helper.js
CHANGED
|
@@ -166,15 +166,6 @@ async function startPeriodic(executor, config) {
|
|
|
166
166
|
|
|
167
167
|
if (triggerBuild) {
|
|
168
168
|
config.causeMessage = 'Started by periodic build scheduler';
|
|
169
|
-
|
|
170
|
-
// Even if post event failed for this event after retry, we should still enqueue the next event
|
|
171
|
-
try {
|
|
172
|
-
await postBuildEvent(executor, config);
|
|
173
|
-
} catch (err) {
|
|
174
|
-
logger.error(
|
|
175
|
-
`periodic builds: failed to post build event for job ${job.id} in pipeline ${pipeline.id}: ${err}`
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
169
|
}
|
|
179
170
|
|
|
180
171
|
if (buildCron && job.state === 'ENABLED' && !job.archived) {
|
|
@@ -214,18 +205,28 @@ async function startPeriodic(executor, config) {
|
|
|
214
205
|
logger.error(`failed to enqueue for job ${job.id}: ${err}`);
|
|
215
206
|
}
|
|
216
207
|
}
|
|
217
|
-
if (!shouldRetry) {
|
|
218
|
-
logger.info(`successfully added to queue for job ${job.id}`);
|
|
219
208
|
|
|
220
|
-
|
|
209
|
+
if (shouldRetry) {
|
|
210
|
+
try {
|
|
211
|
+
await executor.queue.enqueueAt(next, executor.periodicBuildQueue, 'startDelayed', [{ jobId: job.id }]);
|
|
212
|
+
} catch (err) {
|
|
213
|
+
logger.error(`failed to add to delayed queue for job ${job.id}: ${err}`);
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
logger.info(`successfully added to queue for job ${job.id}`);
|
|
221
217
|
}
|
|
218
|
+
}
|
|
219
|
+
logger.info(`added to delayed queue for job ${job.id}`);
|
|
220
|
+
|
|
221
|
+
if (triggerBuild) {
|
|
222
222
|
try {
|
|
223
|
-
await
|
|
223
|
+
await postBuildEvent(executor, config);
|
|
224
224
|
} catch (err) {
|
|
225
|
-
logger.error(
|
|
225
|
+
logger.error(
|
|
226
|
+
`periodic builds: failed to post build event for job ${job.id} in pipeline ${pipeline.id}: ${err}`
|
|
227
|
+
);
|
|
226
228
|
}
|
|
227
229
|
}
|
|
228
|
-
logger.info(`added to delayed queue for job ${job.id}`);
|
|
229
230
|
|
|
230
231
|
return Promise.resolve();
|
|
231
232
|
}
|
|
@@ -405,15 +406,21 @@ async function start(executor, config) {
|
|
|
405
406
|
}
|
|
406
407
|
]);
|
|
407
408
|
if (buildStats) {
|
|
408
|
-
await helper
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
409
|
+
await helper
|
|
410
|
+
.updateBuild(
|
|
411
|
+
{
|
|
412
|
+
buildId,
|
|
413
|
+
token: buildToken,
|
|
414
|
+
apiUri,
|
|
415
|
+
payload: { stats: build.stats, status: 'QUEUED' }
|
|
416
|
+
},
|
|
417
|
+
helper.requestRetryStrategy
|
|
418
|
+
)
|
|
419
|
+
.catch(err => {
|
|
420
|
+
logger.error(`Failed to update build status for build ${buildId}: ${err}`);
|
|
421
|
+
|
|
422
|
+
throw err;
|
|
423
|
+
});
|
|
417
424
|
}
|
|
418
425
|
}
|
|
419
426
|
|
|
@@ -530,8 +537,11 @@ async function init(executor) {
|
|
|
530
537
|
executor.scheduler.on('master', state => logger.info(`scheduler became master ${state}`));
|
|
531
538
|
executor.scheduler.on('error', error => logger.info(`scheduler error >> ${error}`));
|
|
532
539
|
executor.scheduler.on('workingTimestamp', timestamp => logger.info(`scheduler working timestamp ${timestamp}`));
|
|
540
|
+
executor.scheduler.on('cleanStuckWorker', (workerName, errorPayload, delta) =>
|
|
541
|
+
logger.info(`scheduler failing ${workerName} (stuck for ${delta}s) and failing job ${errorPayload}`)
|
|
542
|
+
);
|
|
533
543
|
executor.scheduler.on('transferredJob', (timestamp, job) =>
|
|
534
|
-
logger.info(`scheduler enqueuing job timestamp >> ${JSON.stringify(job)}`)
|
|
544
|
+
logger.info(`scheduler enqueuing job ${timestamp} >> ${JSON.stringify(job)}`)
|
|
535
545
|
);
|
|
536
546
|
|
|
537
547
|
await executor.multiWorker.start();
|
package/plugins/redis.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Redis = require('ioredis');
|
|
4
|
+
const logger = require('screwdriver-logger');
|
|
5
|
+
const { connectionDetails } = require('../config/redis');
|
|
6
|
+
|
|
7
|
+
const redis = new Redis({
|
|
8
|
+
port: connectionDetails.port,
|
|
9
|
+
host: connectionDetails.host,
|
|
10
|
+
password: connectionDetails.options.password,
|
|
11
|
+
tls: connectionDetails.options.tls
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
redis.on('connecting', () => {
|
|
15
|
+
logger.info('Connecting to Redis.');
|
|
16
|
+
});
|
|
17
|
+
redis.on('connect', () => {
|
|
18
|
+
logger.info('Successfully connected to Redis');
|
|
19
|
+
});
|
|
20
|
+
redis.on('error', err => {
|
|
21
|
+
if (err.code === 'ECONNREFUSED') {
|
|
22
|
+
logger.error(`Could not connect to Redis: ${err.message}.`);
|
|
23
|
+
} else {
|
|
24
|
+
logger.error(`Redis encountered an error: ${err.message}.`);
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
module.exports = redis;
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
const NodeResque = require('node-resque');
|
|
4
4
|
const hoek = require('@hapi/hoek');
|
|
5
5
|
const logger = require('screwdriver-logger');
|
|
6
|
-
const Redis = require('ioredis');
|
|
7
6
|
const Redlock = require('redlock');
|
|
8
7
|
const helper = require('../../helper');
|
|
9
|
-
const {
|
|
10
|
-
const redis =
|
|
8
|
+
const { runningJobsPrefix, waitingJobsPrefix, queuePrefix } = require('../../../config/redis');
|
|
9
|
+
const redis = require('../../redis');
|
|
11
10
|
// https://github.com/mike-marcacci/node-redlock
|
|
12
11
|
const redlock = new Redlock([redis], {
|
|
13
12
|
driftFactor: 0.01, // time in ms
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const amqp = require('amqp-connection-manager');
|
|
4
|
-
const Redis = require('ioredis');
|
|
5
4
|
const config = require('config');
|
|
6
5
|
const hoek = require('@hapi/hoek');
|
|
7
6
|
const ExecutorRouter = require('screwdriver-executor-router');
|
|
@@ -12,7 +11,7 @@ const { BlockedBy } = require('./BlockedBy');
|
|
|
12
11
|
const { Filter } = require('./Filter');
|
|
13
12
|
const { CacheFilter } = require('./CacheFilter');
|
|
14
13
|
const blockedByConfig = config.get('plugins').blockedBy;
|
|
15
|
-
const {
|
|
14
|
+
const { queuePrefix, runningJobsPrefix, waitingJobsPrefix } = require('../../../config/redis');
|
|
16
15
|
const rabbitmqConf = require('../../../config/rabbitmq');
|
|
17
16
|
const { amqpURI, exchange, connectOptions } = rabbitmqConf.getConfig();
|
|
18
17
|
const kafkaConfig = require('../../../config/kafka');
|
|
@@ -21,8 +20,7 @@ const RETRY_LIMIT = 3;
|
|
|
21
20
|
// This is in milliseconds, reference: https://github.com/actionhero/node-resque/blob/2ffdf0/lib/plugins/Retry.js#L12
|
|
22
21
|
const RETRY_DELAY = 5 * 1000;
|
|
23
22
|
const DEFAULT_BUILD_TIMEOUT = 90;
|
|
24
|
-
const redis =
|
|
25
|
-
|
|
23
|
+
const redis = require('../../redis');
|
|
26
24
|
const ecosystem = config.get('ecosystem');
|
|
27
25
|
const executorConfig = config.get('executor');
|
|
28
26
|
|
package/plugins/worker/worker.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const NodeResque = require('node-resque');
|
|
4
4
|
const config = require('config');
|
|
5
|
-
const Redis = require('ioredis');
|
|
6
5
|
const logger = require('screwdriver-logger');
|
|
7
6
|
const Redlock = require('redlock');
|
|
8
7
|
const jobs = require('./lib/jobs');
|
|
@@ -10,7 +9,7 @@ const timeout = require('./lib/timeout');
|
|
|
10
9
|
const helper = require('../helper');
|
|
11
10
|
const workerConfig = config.get('worker');
|
|
12
11
|
const { connectionDetails, queuePrefix } = require('../../config/redis');
|
|
13
|
-
const redis =
|
|
12
|
+
const redis = require('../redis');
|
|
14
13
|
// https://github.com/mike-marcacci/node-redlock
|
|
15
14
|
const redlock = new Redlock([redis], {
|
|
16
15
|
driftFactor: 0.01, // time in ms
|
|
@@ -86,29 +85,27 @@ async function invoke() {
|
|
|
86
85
|
logger.info(`queueWorker->worker[${workerId}] ${job} success ${queue} ${JSON.stringify(job)} >> ${result}`)
|
|
87
86
|
);
|
|
88
87
|
multiWorker.on('failure', (workerId, queue, job, failure) =>
|
|
89
|
-
helper
|
|
90
|
-
{
|
|
88
|
+
helper
|
|
89
|
+
.updateBuildStatus({
|
|
91
90
|
redisInstance: redis,
|
|
92
91
|
buildId: job.args[0].buildId,
|
|
93
92
|
status: 'FAILURE',
|
|
94
93
|
statusMessage: `${failure}`
|
|
95
|
-
}
|
|
96
|
-
(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
`
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
)
|
|
94
|
+
})
|
|
95
|
+
.then(() => {
|
|
96
|
+
logger.info(
|
|
97
|
+
`queueWorker->worker[${workerId}] ${JSON.stringify(job)} ` +
|
|
98
|
+
`failure ${queue} ` +
|
|
99
|
+
`${JSON.stringify(job)} >> successfully update build status: ${failure}`
|
|
100
|
+
);
|
|
101
|
+
})
|
|
102
|
+
.catch(err => {
|
|
103
|
+
logger.error(
|
|
104
|
+
`queueWorker->worker[${workerId}] ${job} failure ` +
|
|
105
|
+
`${queue} ${JSON.stringify(job)} ` +
|
|
106
|
+
`>> ${failure} ${err}`
|
|
107
|
+
);
|
|
108
|
+
})
|
|
112
109
|
);
|
|
113
110
|
multiWorker.on('error', (workerId, queue, job, error) =>
|
|
114
111
|
logger.error(`queueWorker->worker[${workerId}] error ${queue} ${JSON.stringify(job)} >> ${error}`)
|
|
@@ -126,13 +123,17 @@ async function invoke() {
|
|
|
126
123
|
scheduler.on('poll', () => logger.info('queueWorker->scheduler polling'));
|
|
127
124
|
scheduler.on('master', state => logger.info(`queueWorker->scheduler became master ${state}`));
|
|
128
125
|
scheduler.on('error', error => logger.info(`queueWorker->scheduler error >> ${error}`));
|
|
129
|
-
scheduler.on('
|
|
126
|
+
scheduler.on('workingTimestamp', timestamp =>
|
|
130
127
|
logger.info(`queueWorker->scheduler working timestamp ${timestamp}`)
|
|
131
128
|
);
|
|
132
|
-
scheduler.on('
|
|
129
|
+
scheduler.on('transferredJob', (timestamp, job) =>
|
|
133
130
|
logger.info(`queueWorker->scheduler enqueuing job timestamp >> ${timestamp} ${JSON.stringify(job)}`)
|
|
134
131
|
);
|
|
135
|
-
|
|
132
|
+
scheduler.on('cleanStuckWorker', (workerName, errorPayload, delta) =>
|
|
133
|
+
logger.info(
|
|
134
|
+
`queueWorker->scheduler failing ${workerName} (stuck for ${delta}s) and failing job ${errorPayload}`
|
|
135
|
+
)
|
|
136
|
+
);
|
|
136
137
|
multiWorker.start();
|
|
137
138
|
|
|
138
139
|
await scheduler.connect();
|