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 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 = new Redis(redisConnection.port, redisConnection.host, redisConnection.options);
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.34",
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": "^3.2.2",
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
@@ -76,7 +76,7 @@ function formatOptions(method, url, token, json, retryStrategyFn) {
76
76
  });
77
77
  }
78
78
 
79
- logger.info(`${options.method} ${options.uri}`);
79
+ logger.info(`${options.method} ${options.url}`);
80
80
 
81
81
  return options;
82
82
  }
@@ -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
- return Promise.resolve();
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 executor.queue.enqueueAt(next, executor.periodicBuildQueue, 'startDelayed', [{ jobId: job.id }]);
223
+ await postBuildEvent(executor, config);
224
224
  } catch (err) {
225
- logger.error(`failed to add to delayed queue for job ${job.id}: ${err}`);
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.updateBuild(
409
- {
410
- buildId,
411
- token: buildToken,
412
- apiUri,
413
- payload: { stats: build.stats, status: 'QUEUED' }
414
- },
415
- helper.requestRetryStrategy
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();
@@ -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 { connectionDetails, runningJobsPrefix, waitingJobsPrefix, queuePrefix } = require('../../../config/redis');
10
- const redis = new Redis(connectionDetails.port, connectionDetails.host, connectionDetails.options);
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 { connectionDetails, queuePrefix, runningJobsPrefix, waitingJobsPrefix } = require('../../../config/redis');
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 = new Redis(connectionDetails.port, connectionDetails.host, connectionDetails.options);
25
-
23
+ const redis = require('../../redis');
26
24
  const ecosystem = config.get('ecosystem');
27
25
  const executorConfig = config.get('executor');
28
26
 
@@ -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 = new Redis(connectionDetails.port, connectionDetails.host, connectionDetails.options);
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.updateBuildStatus(
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
- (err, response) => {
97
- if (!err) {
98
- logger.info(
99
- `queueWorker->worker[${workerId}] ${JSON.stringify(job)} ` +
100
- `failure ${queue} ` +
101
- `${JSON.stringify(job)} >> successfully update build status: ${failure}`
102
- );
103
- } else {
104
- logger.error(
105
- `queueWorker->worker[${workerId}] ${job} failure ` +
106
- `${queue} ${JSON.stringify(job)} ` +
107
- `>> ${failure} ${err} ${JSON.stringify(response)}`
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('working_timestamp', timestamp =>
126
+ scheduler.on('workingTimestamp', timestamp =>
130
127
  logger.info(`queueWorker->scheduler working timestamp ${timestamp}`)
131
128
  );
132
- scheduler.on('transferred_job', (timestamp, job) =>
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();