1
0
Fork 0

Merge pull request #1140 from actions/segment-download-timeout

Introducing timeout in segment download to avoid the download stuck problem
pull/1150/head
Sankalp Kotewar 2022-08-09 16:18:25 +05:30 committed by GitHub
commit d714ea08d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 70 deletions

67
package-lock.json generated
View File

@ -9004,9 +9004,9 @@
} }
}, },
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.10.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"has": "^1.0.3" "has": "^1.0.3"
@ -12996,38 +12996,6 @@
"node-gyp-build-test": "build-test.js" "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": { "node_modules/node-gyp/node_modules/semver": {
"version": "7.3.7", "version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
@ -23272,9 +23240,9 @@
} }
}, },
"is-core-module": { "is-core-module": {
"version": "2.10.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
"integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
"dev": true, "dev": true,
"requires": { "requires": {
"has": "^1.0.3" "has": "^1.0.3"
@ -26287,29 +26255,6 @@
"which": "^2.0.2" "which": "^2.0.2"
}, },
"dependencies": { "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": { "semver": {
"version": "7.3.7", "version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",

View File

@ -74,4 +74,7 @@
### 3.0.1 ### 3.0.1
- Fix [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory. - 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. - 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).

View File

@ -8,6 +8,7 @@ import {
const useAzureSdk = true const useAzureSdk = true
const downloadConcurrency = 8 const downloadConcurrency = 8
const timeoutInMs = 30000 const timeoutInMs = 30000
const segmentTimeoutInMs = 3600000
const uploadConcurrency = 4 const uploadConcurrency = 4
const uploadChunkSize = 32 * 1024 * 1024 const uploadChunkSize = 32 * 1024 * 1024
@ -17,7 +18,8 @@ test('getDownloadOptions sets defaults', async () => {
expect(actualOptions).toEqual({ expect(actualOptions).toEqual({
useAzureSdk, useAzureSdk,
downloadConcurrency, downloadConcurrency,
timeoutInMs timeoutInMs,
segmentTimeoutInMs
}) })
}) })
@ -25,7 +27,8 @@ test('getDownloadOptions overrides all settings', async () => {
const expectedOptions: DownloadOptions = { const expectedOptions: DownloadOptions = {
useAzureSdk: false, useAzureSdk: false,
downloadConcurrency: 14, downloadConcurrency: 14,
timeoutInMs: 20000 timeoutInMs: 20000,
segmentTimeoutInMs: 3600000
} }
const actualOptions = getDownloadOptions(expectedOptions) const actualOptions = getDownloadOptions(expectedOptions)

4
packages/cache/package-lock.json generated vendored
View File

@ -1,12 +1,12 @@
{ {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.0.1", "version": "3.0.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.0.1", "version": "3.0.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.2.6",

View File

@ -1,6 +1,6 @@
{ {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.0.1", "version": "3.0.2",
"preview": true, "preview": true,
"description": "Actions cache lib", "description": "Actions cache lib",
"keywords": [ "keywords": [

View File

@ -12,6 +12,8 @@ import {SocketTimeout} from './constants'
import {DownloadOptions} from '../options' import {DownloadOptions} from '../options'
import {retryHttpClientResponse} from './requestUtils' import {retryHttpClientResponse} from './requestUtils'
import {AbortController} from '@azure/abort-controller'
/** /**
* Pipes the body of a HTTP response to a stream * Pipes the body of a HTTP response to a stream
* *
@ -247,7 +249,12 @@ export async function downloadCacheStorageSDK(
try { try {
downloadProgress.startDisplayTimer() 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()) { while (!downloadProgress.isDone()) {
const segmentStart = const segmentStart =
downloadProgress.segmentOffset + downloadProgress.segmentSize downloadProgress.segmentOffset + downloadProgress.segmentSize
@ -263,11 +270,11 @@ export async function downloadCacheStorageSDK(
segmentStart, segmentStart,
segmentSize, segmentSize,
{ {
abortSignal,
concurrency: options.downloadConcurrency, concurrency: options.downloadConcurrency,
onProgress: downloadProgress.onProgress() onProgress: downloadProgress.onProgress()
} }
) )
fs.writeFileSync(fd, result) fs.writeFileSync(fd, result)
} }
} finally { } finally {

View File

@ -46,6 +46,13 @@ export interface DownloadOptions {
* @default 30000 * @default 30000
*/ */
timeoutInMs?: number 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 = { const result: DownloadOptions = {
useAzureSdk: true, useAzureSdk: true,
downloadConcurrency: 8, downloadConcurrency: 8,
timeoutInMs: 30000 timeoutInMs: 30000,
segmentTimeoutInMs: 3600000
} }
if (copy) { if (copy) {
@ -99,11 +107,16 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
if (typeof copy.timeoutInMs === 'number') { if (typeof copy.timeoutInMs === 'number') {
result.timeoutInMs = copy.timeoutInMs result.timeoutInMs = copy.timeoutInMs
} }
if (typeof copy.segmentTimeoutInMs === 'number') {
result.segmentTimeoutInMs = copy.segmentTimeoutInMs
}
} }
core.debug(`Use Azure SDK: ${result.useAzureSdk}`) core.debug(`Use Azure SDK: ${result.useAzureSdk}`)
core.debug(`Download concurrency: ${result.downloadConcurrency}`) core.debug(`Download concurrency: ${result.downloadConcurrency}`)
core.debug(`Request timeout (ms): ${result.timeoutInMs}`) core.debug(`Request timeout (ms): ${result.timeoutInMs}`)
core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`)
return result return result
} }