Merge pull request #1140 from actions/segment-download-timeout
Introducing timeout in segment download to avoid the download stuck problem
This commit is contained in:
commit
ef9bbab1f6
6 files changed
+34
-8
No files matched your search
@@ -75,3 +75,6 @@
|
|||||||
### 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).
|
||||||
@@ -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)
|
||||||
|
|||||||
Generated
+2
-2
@@ -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",
|
||||||
|
|||||||
+1
-1
@@ -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": [
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
+14
-1
@@ -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
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user