Skip to content

Commit a17483c

Browse files
authored
Merge pull request #712 from proactivebit/issue/download-logs-connection-reset
fix(download-logs): retry download logs fixes #711
2 parents f74a238 + efb6789 commit a17483c

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/cloudmanager-helpers.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const Config = require('@adobe/aio-lib-core-config')
1414
const { init } = require('@adobe/aio-lib-cloudmanager')
1515
const { cli } = require('cli-ux')
1616
const { context, getToken, Ims } = require('@adobe/aio-lib-ims')
17-
const logger = require('@adobe/aio-lib-core-logging')('@adobe/aio-lib-cloudmanager', { provider: 'debug' })
17+
const logger = require('@adobe/aio-lib-core-logging')('@adobe/aio-lib-cloudmanager', { level: process.env.LOG_LEVEL })
1818
const moment = require('moment')
1919
const _ = require('lodash')
2020
const { CLI } = require('@adobe/aio-lib-ims/src/context')
@@ -338,6 +338,18 @@ function shouldResetRetires (startTime, resetInterval = 3600000) {
338338
return false
339339
}
340340

341+
async function executeWithRetry (fn, retries = 3, delay = 1000) {
342+
for (let i = 0; i < retries; i++) {
343+
try {
344+
return await fn()
345+
} catch (error) {
346+
logger.debug(`Retrying due to error: ${error.message || 'Unknown error'} (attempt ${i + 1}/${retries})`)
347+
if (i === retries - 1) throw error
348+
await new Promise(resolve => setTimeout(resolve, delay))
349+
}
350+
}
351+
}
352+
341353
module.exports = {
342354
getProgramId,
343355
getOutputFormat,
@@ -361,4 +373,5 @@ module.exports = {
361373
getFullOrgIdentity,
362374
handleError,
363375
executeWithRetries,
376+
executeWithRetry,
364377
}

src/commands/cloudmanager/environment/download-logs.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ governing permissions and limitations under the License.
1111
*/
1212

1313
const { flags } = require('@oclif/command')
14-
const { initSdk, getProgramId, sanitizeEnvironmentId } = require('../../../cloudmanager-helpers')
14+
const { initSdk, getProgramId, sanitizeEnvironmentId, executeWithRetry } = require('../../../cloudmanager-helpers')
1515
const { cli } = require('cli-ux')
1616
const path = require('path')
1717
const commonFlags = require('../../../common-flags')
@@ -50,8 +50,10 @@ class DownloadLogs extends BaseCommand {
5050
}
5151

5252
async downloadLogs (programId, environmentId, service, logName, days, outputDirectory, imsContextName = null) {
53-
const sdk = await initSdk(imsContextName)
54-
return sdk.downloadLogs(programId, environmentId, service, logName, days, outputDirectory)
53+
return executeWithRetry(async () => {
54+
const sdk = await initSdk(imsContextName)
55+
return sdk.downloadLogs(programId, environmentId, service, logName, days, outputDirectory)
56+
})
5557
}
5658
}
5759

test/cloudmanager-helpers.test.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ governing permissions and limitations under the License.
1212

1313
const { setCurrentOrgId, context } = require('@adobe/aio-lib-ims')
1414
const { setStore } = require('@adobe/aio-lib-core-config')
15-
const { initSdk, getOutputFormat, columnWithArray, disableCliAuth, enableCliAuth, formatDuration, executeWithRetries } = require('../src/cloudmanager-helpers')
15+
const { initSdk, getOutputFormat, columnWithArray, disableCliAuth, enableCliAuth, formatDuration, executeWithRetries, executeWithRetry } = require('../src/cloudmanager-helpers')
1616
const { init } = require('@adobe/aio-lib-cloudmanager')
1717
const { setDecodedToken, resetDecodedToken } = require('jsonwebtoken')
1818

@@ -196,3 +196,36 @@ describe('executeWithRetries', () => {
196196
expect(mockFn.mock.calls.length).toEqual(6)
197197
})
198198
})
199+
200+
describe('executeWithRetry', () => {
201+
afterEach(() => {
202+
jest.restoreAllMocks()
203+
})
204+
205+
test('should not retry when function succeed', async () => {
206+
const mockFn = jest.fn().mockResolvedValue('success')
207+
208+
executeWithRetry(mockFn)
209+
210+
expect(mockFn.mock.calls.length).toEqual(1)
211+
})
212+
213+
test('should retry when error thrown', async () => {
214+
const mockFn = jest.fn()
215+
.mockRejectedValueOnce({})
216+
.mockResolvedValue('success')
217+
218+
await executeWithRetry(mockFn)
219+
220+
expect(mockFn.mock.calls.length).toEqual(2)
221+
})
222+
223+
test('should throw error after 3 attempts', async () => {
224+
const mockFn = jest.fn()
225+
.mockRejectedValue(new Error())
226+
227+
await expect(executeWithRetry(mockFn)).rejects.toThrow()
228+
229+
expect(mockFn.mock.calls.length).toEqual(3)
230+
})
231+
})

0 commit comments

Comments
 (0)