diff --git a/packages/cache/README.md b/packages/cache/README.md index 541b1155..eaa30e7b 100644 --- a/packages/cache/README.md +++ b/packages/cache/README.md @@ -42,3 +42,8 @@ const restoreKeys = [ const cacheKey = await cache.restoreCache(paths, key, restoreKeys) ``` +##### Cache segment restore timeout + +A cache gets downloaded in multiple segments of fixed sizes (`1GB` for a `32-bit` runner and `2GB` for a `64-bit` runner). Sometimes, a segment download gets stuck which causes the workflow job to be stuck forever and fail. Version `v3.0.4` of cache package introduces a segment download timeout. The segment download timeout will allow the segment download to get aborted and hence allow the job to proceed with a cache miss. + +Default value of this timeout is 60 minutes and can be customized by specifying an [environment variable](https://docs.github.com/en/actions/learn-github-actions/environment-variables) named `SEGMENT_DOWNLOAD_TIMEOUT_MINS` with timeout value in minutes. \ No newline at end of file diff --git a/packages/cache/RELEASES.md b/packages/cache/RELEASES.md index 749afb33..77ca90cc 100644 --- a/packages/cache/RELEASES.md +++ b/packages/cache/RELEASES.md @@ -83,4 +83,5 @@ - Bug fixes for download stuck issue [#810](https://github.com/actions/cache/issues/810). ### 3.0.4 -- Fix zstd not working for windows on gnu tar in issues [#888](https://github.com/actions/cache/issues/888) and [#891](https://github.com/actions/cache/issues/891). \ No newline at end of file +- Fix zstd not working for windows on gnu tar in issues [#888](https://github.com/actions/cache/issues/888) and [#891](https://github.com/actions/cache/issues/891). +- Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MIN`. Default is 60 minutes. diff --git a/packages/cache/__tests__/options.test.ts b/packages/cache/__tests__/options.test.ts index 5ec7b146..83d9b227 100644 --- a/packages/cache/__tests__/options.test.ts +++ b/packages/cache/__tests__/options.test.ts @@ -55,3 +55,21 @@ test('getUploadOptions overrides all settings', async () => { expect(actualOptions).toEqual(expectedOptions) }) + +test('getDownloadOptions overrides download timeout minutes', async () => { + const expectedOptions: DownloadOptions = { + useAzureSdk: false, + downloadConcurrency: 14, + timeoutInMs: 20000, + segmentTimeoutInMs: 3600000 + } + process.env.SEGMENT_DOWNLOAD_TIMEOUT_MINS = '10' + const actualOptions = getDownloadOptions(expectedOptions) + + expect(actualOptions.useAzureSdk).toEqual(expectedOptions.useAzureSdk) + expect(actualOptions.downloadConcurrency).toEqual( + expectedOptions.downloadConcurrency + ) + expect(actualOptions.timeoutInMs).toEqual(expectedOptions.timeoutInMs) + expect(actualOptions.segmentTimeoutInMs).toEqual(600000) +}) diff --git a/packages/cache/src/internal/tar.ts b/packages/cache/src/internal/tar.ts index 34229ccf..3dee7fd0 100644 --- a/packages/cache/src/internal/tar.ts +++ b/packages/cache/src/internal/tar.ts @@ -3,7 +3,7 @@ import * as io from '@actions/io' import {existsSync, writeFileSync} from 'fs' import * as path from 'path' import * as utils from './cacheUtils' -import {CompressionMethod, TarOperation} from './constants' +import {CompressionMethod} from './constants' const IS_WINDOWS = process.platform === 'win32' diff --git a/packages/cache/src/options.ts b/packages/cache/src/options.ts index eefe9731..652899a2 100644 --- a/packages/cache/src/options.ts +++ b/packages/cache/src/options.ts @@ -112,10 +112,22 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { result.segmentTimeoutInMs = copy.segmentTimeoutInMs } } + const segmentDownloadTimeoutMins = + process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS'] + if ( + segmentDownloadTimeoutMins && + !isNaN(Number(segmentDownloadTimeoutMins)) && + isFinite(Number(segmentDownloadTimeoutMins)) + ) { + result.segmentTimeoutInMs = Number(segmentDownloadTimeoutMins) * 60 * 1000 + } core.debug(`Use Azure SDK: ${result.useAzureSdk}`) core.debug(`Download concurrency: ${result.downloadConcurrency}`) core.debug(`Request timeout (ms): ${result.timeoutInMs}`) + core.debug( + `Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}` + ) core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`) return result