diff --git a/lib/logic/__tests__/workflows.logic.unit.spec.js b/lib/logic/__tests__/workflows.logic.unit.spec.js new file mode 100644 index 0000000..fee9a21 --- /dev/null +++ b/lib/logic/__tests__/workflows.logic.unit.spec.js @@ -0,0 +1,55 @@ +const _ = require('lodash'); +const moment = require('moment'); +const Workflows = require('../workflows.logic'); + +jest.setTimeout(2000); +let sdk; +let wf; +describe('workflows logic', () => { + beforeEach(() => { + sdk = jest.mock(); + wf = new Workflows(sdk); + wf.delay = 500; + }); + it('success', async () => { + _.set(sdk, 'workflows.getBuild', async () => ({ status: 'success' })); + const result = await wf.waitForStatus('id', 'success', moment().add(200, 'ms')); + expect(result.status).toBe('success'); + }); + + it('success after retries', async () => { + let i = 0; + _.set(sdk, 'workflows.getBuild', + async () => { + if (i < 2) { i += 1; throw new Error('simulate error'); } + return { status: 'success' }; + }); + const result = await wf.waitForStatus('id', 'success', moment().add(200, 'ms')); + expect(result.status).toBe('success'); + }); + + it('timeout', async () => { + const status = 'running'; + _.set(sdk, 'workflows.getBuild', + async () => ({ status })); + try { + await wf.waitForStatus('id', 'success', moment().add(700, 'ms')); + } catch (err) { + expect(err.message).toBe('Operation has timed out'); + return; // good. + } + throw new Error('Failed, should have time out'); + }); + + it('running then success', async () => { + let status = 'running'; + _.set(sdk, 'workflows.getBuild', + async () => { + const current = status; + status = 'success'; + return { status: current }; + }); + const result = await wf.waitForStatus('id', 'success', moment().add(700, 'ms')); + expect(result.status).toBe('success'); + }); +}); diff --git a/lib/logic/workflows.logic.js b/lib/logic/workflows.logic.js index a4fadad..d777fac 100644 --- a/lib/logic/workflows.logic.js +++ b/lib/logic/workflows.logic.js @@ -7,13 +7,18 @@ const Resource = require('./Resource.base'); const END_STATUSES = ['error', 'success', 'terminated']; class Workflows extends Resource { + constructor(sdk) { + super(sdk); + this.delay = 5000; + } + async waitForStatus(workflowId, desiredStatus, timeoutDate, descriptive) { const currentDate = moment(); if (currentDate.isAfter(timeoutDate)) { throw new CFError('Operation has timed out'); } - const workflow = await this.sdk.workflows.getBuild({ buildId: workflowId, noAccount: false }); + const workflow = await this.getWorkflow(workflowId); const currentStatus = workflow.status; if (currentStatus !== desiredStatus) { @@ -23,12 +28,30 @@ class Workflows extends Resource { if (descriptive) { console.log(`Workflow: ${workflowId} current status: ${currentStatus}`); } - await Promise.delay(5000); + await Promise.delay(this.delay); return this.waitForStatus(workflowId, desiredStatus, timeoutDate, descriptive); } return workflow; } + + /** + * return workflow + * retry 3 times, if failed throw + */ + async getWorkflow(workflowId) { + let err; + for (let i = 0; i < 3; i += 1) { + try { + // eslint-disable-next-line no-await-in-loop + return await this.sdk.workflows.getBuild({ buildId: workflowId, noAccount: false }); + } catch (e) { + console.warn(`retrying getBuild({buildId: ${workflowId}})`); + err = e; + } + } + throw err; + } } module.exports = Workflows; diff --git a/package.json b/package.json index 276ea2a..85313cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codefresh-sdk", - "version": "1.9.23", + "version": "1.9.24", "description": "Codefresh_api_swagger_3_0_specification", "main": "index.js", "author": {