diff --git a/package-lock.json b/package-lock.json index 0eb36b79aa..2d0a611bd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9004,9 +9004,9 @@ } }, "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -12996,38 +12996,6 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/node-gyp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/node-gyp/node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -23272,9 +23240,9 @@ } }, "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "requires": { "has": "^1.0.3" @@ -26287,29 +26255,6 @@ "which": "^2.0.2" }, "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", diff --git a/packages/cache/RELEASES.md b/packages/cache/RELEASES.md index 931228a39e..34bbace4cd 100644 --- a/packages/cache/RELEASES.md +++ b/packages/cache/RELEASES.md @@ -74,4 +74,7 @@ ### 3.0.1 - Fix [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory. -- Fix [#809](https://github.com/actions/cache/issues/809) `zstd -d: no such file or directory` error on AWS self-hosted runners. \ No newline at end of file +- Fix [#809](https://github.com/actions/cache/issues/809) `zstd -d: no such file or directory` error on AWS self-hosted runners. + +### 3.0.2 +- Added 1 hour timeout for the download stuck issue [#810](https://github.com/actions/cache/issues/810). \ No newline at end of file diff --git a/packages/cache/__tests__/options.test.ts b/packages/cache/__tests__/options.test.ts index 3075b43b5b..5ec7b1461a 100644 --- a/packages/cache/__tests__/options.test.ts +++ b/packages/cache/__tests__/options.test.ts @@ -8,6 +8,7 @@ import { const useAzureSdk = true const downloadConcurrency = 8 const timeoutInMs = 30000 +const segmentTimeoutInMs = 3600000 const uploadConcurrency = 4 const uploadChunkSize = 32 * 1024 * 1024 @@ -17,7 +18,8 @@ test('getDownloadOptions sets defaults', async () => { expect(actualOptions).toEqual({ useAzureSdk, downloadConcurrency, - timeoutInMs + timeoutInMs, + segmentTimeoutInMs }) }) @@ -25,7 +27,8 @@ test('getDownloadOptions overrides all settings', async () => { const expectedOptions: DownloadOptions = { useAzureSdk: false, downloadConcurrency: 14, - timeoutInMs: 20000 + timeoutInMs: 20000, + segmentTimeoutInMs: 3600000 } const actualOptions = getDownloadOptions(expectedOptions) diff --git a/packages/cache/package-lock.json b/packages/cache/package-lock.json index de8c7e0fc0..05de404eb9 100644 --- a/packages/cache/package-lock.json +++ b/packages/cache/package-lock.json @@ -1,12 +1,12 @@ { "name": "@actions/cache", - "version": "3.0.1", + "version": "3.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@actions/cache", - "version": "3.0.1", + "version": "3.0.2", "license": "MIT", "dependencies": { "@actions/core": "^1.2.6", diff --git a/packages/cache/package.json b/packages/cache/package.json index 19d065bd3d..26b02f06bd 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@actions/cache", - "version": "3.0.1", + "version": "3.0.2", "preview": true, "description": "Actions cache lib", "keywords": [ diff --git a/packages/cache/src/internal/downloadUtils.ts b/packages/cache/src/internal/downloadUtils.ts index 08b2dee80e..c92cc99969 100644 --- a/packages/cache/src/internal/downloadUtils.ts +++ b/packages/cache/src/internal/downloadUtils.ts @@ -12,6 +12,8 @@ import {SocketTimeout} from './constants' import {DownloadOptions} from '../options' import {retryHttpClientResponse} from './requestUtils' +import {AbortController} from '@azure/abort-controller' + /** * Pipes the body of a HTTP response to a stream * @@ -247,7 +249,12 @@ export async function downloadCacheStorageSDK( try { downloadProgress.startDisplayTimer() - + const abortSignal = AbortController.timeout( + options.segmentTimeoutInMs || 3600000 + ) + abortSignal.addEventListener('abort', () => { + core.warning('Aborting cache download as it exceeded the timeout.') + }) while (!downloadProgress.isDone()) { const segmentStart = downloadProgress.segmentOffset + downloadProgress.segmentSize @@ -263,11 +270,11 @@ export async function downloadCacheStorageSDK( segmentStart, segmentSize, { + abortSignal, concurrency: options.downloadConcurrency, onProgress: downloadProgress.onProgress() } ) - fs.writeFileSync(fd, result) } } finally { diff --git a/packages/cache/src/options.ts b/packages/cache/src/options.ts index 94642fd3c6..eefe973144 100644 --- a/packages/cache/src/options.ts +++ b/packages/cache/src/options.ts @@ -46,6 +46,13 @@ export interface DownloadOptions { * @default 30000 */ timeoutInMs?: number + + /** + * Time after which a segment download should be aborted if stuck + * + * @default 3600000 + */ + segmentTimeoutInMs?: number } /** @@ -84,7 +91,8 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { const result: DownloadOptions = { useAzureSdk: true, downloadConcurrency: 8, - timeoutInMs: 30000 + timeoutInMs: 30000, + segmentTimeoutInMs: 3600000 } if (copy) { @@ -99,11 +107,16 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions { if (typeof copy.timeoutInMs === 'number') { result.timeoutInMs = copy.timeoutInMs } + + if (typeof copy.segmentTimeoutInMs === 'number') { + result.segmentTimeoutInMs = copy.segmentTimeoutInMs + } } core.debug(`Use Azure SDK: ${result.useAzureSdk}`) core.debug(`Download concurrency: ${result.downloadConcurrency}`) core.debug(`Request timeout (ms): ${result.timeoutInMs}`) + core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`) return result }