screwdriver-queue-service 2.0.36 → 2.0.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screwdriver-queue-service",
3
- "version": "2.0.36",
3
+ "version": "2.0.39",
4
4
  "description": "Screwdriver Queue Service API",
5
5
  "main": "app.js",
6
6
  "directories": {
@@ -38,7 +38,7 @@
38
38
  "screwdriver-logger": "^1.0.2",
39
39
  "screwdriver-request": "^1.0.2",
40
40
  "string-hash": "^1.1.3",
41
- "uuid": "^7.0.2"
41
+ "uuid": "^8.0.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "chai": "^4.3.4",
package/plugins/helper.js CHANGED
@@ -247,6 +247,29 @@ async function updateBuild(updateConfig, retryStrategyFn) {
247
247
  );
248
248
  }
249
249
 
250
+ /**
251
+ * Notify user with job status
252
+ * @param {Number} jobId
253
+ * @param {String} token
254
+ * @param {Object} payload
255
+ * @param {String} apiUri
256
+ * @param {Object} retryStrategyFn
257
+ */
258
+ async function notifyJob(notifyConfig, retryStrategyFn) {
259
+ const { token, apiUri, jobId, payload } = notifyConfig;
260
+
261
+ return request(formatOptions('POST', `${apiUri}/v4/jobs/${jobId}/notify`, token, payload, retryStrategyFn)).then(
262
+ res => {
263
+ logger.info(`POST /v4/jobs/${jobId}/notify completed with attempts, ${res.statusCode}, ${res.attempts}`);
264
+ if ([200, 201, 204].includes(res.statusCode)) {
265
+ return res.body;
266
+ }
267
+
268
+ throw new Error(`Could not notify job ${jobId} with ${res.statusCode}code and ${JSON.stringify(res.body)}`);
269
+ }
270
+ );
271
+ }
272
+
250
273
  /**
251
274
  * Post the webhooks process
252
275
  * @method processHooks
@@ -306,5 +329,6 @@ module.exports = {
306
329
  createBuildEvent,
307
330
  getPipelineAdmin,
308
331
  updateBuild,
332
+ notifyJob,
309
333
  processHooks
310
334
  };
@@ -29,12 +29,13 @@ const BLOCKED_BY_SAME_JOB_WAIT_TIME = 5;
29
29
  async function postBuildEvent(executor, eventConfig) {
30
30
  const { pipeline, job, apiUri, eventId, causeMessage, buildId } = eventConfig;
31
31
  const pipelineId = pipeline.id;
32
+ const jobId = job.id;
32
33
 
33
34
  try {
34
35
  const token = executor.tokenGen({
35
36
  pipelineId,
36
37
  service: 'queue',
37
- jobId: job.id,
38
+ jobId,
38
39
  scmContext: pipeline.scmContext,
39
40
  scope: ['user']
40
41
  });
@@ -71,6 +72,26 @@ async function postBuildEvent(executor, eventConfig) {
71
72
  `POST event for pipeline failed as no admin found: ${pipelineId}:${job.name}:${job.id}:${buildId}`
72
73
  );
73
74
 
75
+ const pipelineToken = executor.tokenGen({
76
+ pipelineId,
77
+ service: 'queue',
78
+ scmContext: pipeline.scmContext,
79
+ scope: ['pipeline']
80
+ });
81
+
82
+ const status = 'FAILURE';
83
+ const message = `Pipeline ${pipelineId} does not have admin, unable to start job ${job.name}.`;
84
+
85
+ await helper.notifyJob(
86
+ {
87
+ token: pipelineToken,
88
+ apiUri,
89
+ jobId,
90
+ payload: { status, message }
91
+ },
92
+ helper.requestRetryStrategyPostEvent
93
+ );
94
+
74
95
  throw new Error(`Pipeline admin not found, cannot process build ${buildId}`);
75
96
  }
76
97
  } catch (err) {
@@ -166,15 +187,6 @@ async function startPeriodic(executor, config) {
166
187
 
167
188
  if (triggerBuild) {
168
189
  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
190
  }
179
191
 
180
192
  if (buildCron && job.state === 'ENABLED' && !job.archived) {
@@ -214,18 +226,28 @@ async function startPeriodic(executor, config) {
214
226
  logger.error(`failed to enqueue for job ${job.id}: ${err}`);
215
227
  }
216
228
  }
217
- if (!shouldRetry) {
218
- logger.info(`successfully added to queue for job ${job.id}`);
219
229
 
220
- return Promise.resolve();
230
+ if (shouldRetry) {
231
+ try {
232
+ await executor.queue.enqueueAt(next, executor.periodicBuildQueue, 'startDelayed', [{ jobId: job.id }]);
233
+ } catch (err) {
234
+ logger.error(`failed to add to delayed queue for job ${job.id}: ${err}`);
235
+ }
236
+ } else {
237
+ logger.info(`successfully added to queue for job ${job.id}`);
221
238
  }
239
+ }
240
+ logger.info(`added to delayed queue for job ${job.id}`);
241
+
242
+ if (triggerBuild) {
222
243
  try {
223
- await executor.queue.enqueueAt(next, executor.periodicBuildQueue, 'startDelayed', [{ jobId: job.id }]);
244
+ await postBuildEvent(executor, config);
224
245
  } catch (err) {
225
- logger.error(`failed to add to delayed queue for job ${job.id}: ${err}`);
246
+ logger.error(
247
+ `periodic builds: failed to post build event for job ${job.id} in pipeline ${pipeline.id}: ${err}`
248
+ );
226
249
  }
227
250
  }
228
- logger.info(`added to delayed queue for job ${job.id}`);
229
251
 
230
252
  return Promise.resolve();
231
253
  }
@@ -536,8 +558,11 @@ async function init(executor) {
536
558
  executor.scheduler.on('master', state => logger.info(`scheduler became master ${state}`));
537
559
  executor.scheduler.on('error', error => logger.info(`scheduler error >> ${error}`));
538
560
  executor.scheduler.on('workingTimestamp', timestamp => logger.info(`scheduler working timestamp ${timestamp}`));
561
+ executor.scheduler.on('cleanStuckWorker', (workerName, errorPayload, delta) =>
562
+ logger.info(`scheduler failing ${workerName} (stuck for ${delta}s) and failing job ${errorPayload}`)
563
+ );
539
564
  executor.scheduler.on('transferredJob', (timestamp, job) =>
540
- logger.info(`scheduler enqueuing job timestamp >> ${JSON.stringify(job)}`)
565
+ logger.info(`scheduler enqueuing job ${timestamp} >> ${JSON.stringify(job)}`)
541
566
  );
542
567
 
543
568
  await executor.multiWorker.start();
@@ -123,13 +123,17 @@ async function invoke() {
123
123
  scheduler.on('poll', () => logger.info('queueWorker->scheduler polling'));
124
124
  scheduler.on('master', state => logger.info(`queueWorker->scheduler became master ${state}`));
125
125
  scheduler.on('error', error => logger.info(`queueWorker->scheduler error >> ${error}`));
126
- scheduler.on('working_timestamp', timestamp =>
126
+ scheduler.on('workingTimestamp', timestamp =>
127
127
  logger.info(`queueWorker->scheduler working timestamp ${timestamp}`)
128
128
  );
129
- scheduler.on('transferred_job', (timestamp, job) =>
129
+ scheduler.on('transferredJob', (timestamp, job) =>
130
130
  logger.info(`queueWorker->scheduler enqueuing job timestamp >> ${timestamp} ${JSON.stringify(job)}`)
131
131
  );
132
-
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
+ );
133
137
  multiWorker.start();
134
138
 
135
139
  await scheduler.connect();