mirror of https://github.com/actions/cache.git
Add env var for socket timeout
This commit is contained in:
parent
ce9276c90e
commit
18e62e1fe0
|
@ -2236,6 +2236,13 @@ function createHttpClient() {
|
||||||
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
|
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
|
||||||
return new http_client_1.HttpClient("actions/cache", [bearerCredentialHandler], getRequestOptions());
|
return new http_client_1.HttpClient("actions/cache", [bearerCredentialHandler], getRequestOptions());
|
||||||
}
|
}
|
||||||
|
function parseEnvNumber(key) {
|
||||||
|
const value = Number(process.env[key]);
|
||||||
|
if (Number.isNaN(value) || value < 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
function getCacheVersion(compressionMethod) {
|
function getCacheVersion(compressionMethod) {
|
||||||
const components = [core.getInput(constants_1.Inputs.Path, { required: true })].concat(compressionMethod == constants_1.CompressionMethod.Zstd ? [compressionMethod] : []);
|
const components = [core.getInput(constants_1.Inputs.Path, { required: true })].concat(compressionMethod == constants_1.CompressionMethod.Zstd ? [compressionMethod] : []);
|
||||||
// Add salt to cache version to support breaking changes in cache entry
|
// Add salt to cache version to support breaking changes in cache entry
|
||||||
|
@ -2278,14 +2285,16 @@ function pipeResponseToStream(response, output) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function downloadCache(archiveLocation, archivePath) {
|
function downloadCache(archiveLocation, archivePath) {
|
||||||
|
var _a;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const stream = fs.createWriteStream(archivePath);
|
const stream = fs.createWriteStream(archivePath);
|
||||||
const httpClient = new http_client_1.HttpClient("actions/cache");
|
const httpClient = new http_client_1.HttpClient("actions/cache");
|
||||||
const downloadResponse = yield httpClient.get(archiveLocation);
|
const downloadResponse = yield httpClient.get(archiveLocation);
|
||||||
// Abort download if no traffic received over the socket.
|
// Abort download if no traffic received over the socket.
|
||||||
downloadResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => {
|
const socketTimeout = (_a = parseEnvNumber("CACHE_SOCKET_TIMEOUT"), (_a !== null && _a !== void 0 ? _a : constants_1.DefaultSocketTimeout));
|
||||||
|
downloadResponse.message.socket.setTimeout(socketTimeout, () => {
|
||||||
downloadResponse.message.destroy();
|
downloadResponse.message.destroy();
|
||||||
core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`);
|
core.debug(`Aborting download, socket timed out after ${socketTimeout} ms`);
|
||||||
});
|
});
|
||||||
yield pipeResponseToStream(downloadResponse, stream);
|
yield pipeResponseToStream(downloadResponse, stream);
|
||||||
// Validate download size.
|
// Validate download size.
|
||||||
|
@ -2352,13 +2361,6 @@ function uploadChunk(httpClient, resourceUrl, data, start, end) {
|
||||||
throw new Error(`Cache service responded with ${response.message.statusCode} during chunk upload.`);
|
throw new Error(`Cache service responded with ${response.message.statusCode} during chunk upload.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function parseEnvNumber(key) {
|
|
||||||
const value = Number(process.env[key]);
|
|
||||||
if (Number.isNaN(value) || value < 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
function uploadFile(httpClient, cacheId, archivePath) {
|
function uploadFile(httpClient, cacheId, archivePath) {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
@ -3642,6 +3644,12 @@ class HttpClientResponse {
|
||||||
this.message.on('data', (chunk) => {
|
this.message.on('data', (chunk) => {
|
||||||
output = Buffer.concat([output, chunk]);
|
output = Buffer.concat([output, chunk]);
|
||||||
});
|
});
|
||||||
|
this.message.on('aborted', () => {
|
||||||
|
reject("Request was aborted or closed prematurely");
|
||||||
|
});
|
||||||
|
this.message.on('timeout', (socket) => {
|
||||||
|
reject("Request timed out");
|
||||||
|
});
|
||||||
this.message.on('end', () => {
|
this.message.on('end', () => {
|
||||||
resolve(output.toString());
|
resolve(output.toString());
|
||||||
});
|
});
|
||||||
|
@ -3763,6 +3771,7 @@ class HttpClient {
|
||||||
let response;
|
let response;
|
||||||
while (numTries < maxTries) {
|
while (numTries < maxTries) {
|
||||||
response = await this.requestRaw(info, data);
|
response = await this.requestRaw(info, data);
|
||||||
|
|
||||||
// Check if it's an authentication challenge
|
// Check if it's an authentication challenge
|
||||||
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
|
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
|
||||||
let authenticationHandler;
|
let authenticationHandler;
|
||||||
|
@ -3874,6 +3883,7 @@ class HttpClient {
|
||||||
req.on('error', function (err) {
|
req.on('error', function (err) {
|
||||||
// err has statusCode property
|
// err has statusCode property
|
||||||
// res should have headers
|
// res should have headers
|
||||||
|
console.log(`Caught error on request: ${err}`);
|
||||||
handleResult(err, null);
|
handleResult(err, null);
|
||||||
});
|
});
|
||||||
if (data && typeof (data) === 'string') {
|
if (data && typeof (data) === 'string') {
|
||||||
|
@ -4539,7 +4549,7 @@ var CompressionMethod;
|
||||||
// Socket timeout in milliseconds during download. If no traffic is received
|
// Socket timeout in milliseconds during download. If no traffic is received
|
||||||
// over the socket during this period, the socket is destroyed and the download
|
// over the socket during this period, the socket is destroyed and the download
|
||||||
// is aborted.
|
// is aborted.
|
||||||
exports.SocketTimeout = 5000;
|
exports.DefaultSocketTimeout = 5000;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
|
@ -2236,6 +2236,13 @@ function createHttpClient() {
|
||||||
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
|
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
|
||||||
return new http_client_1.HttpClient("actions/cache", [bearerCredentialHandler], getRequestOptions());
|
return new http_client_1.HttpClient("actions/cache", [bearerCredentialHandler], getRequestOptions());
|
||||||
}
|
}
|
||||||
|
function parseEnvNumber(key) {
|
||||||
|
const value = Number(process.env[key]);
|
||||||
|
if (Number.isNaN(value) || value < 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
function getCacheVersion(compressionMethod) {
|
function getCacheVersion(compressionMethod) {
|
||||||
const components = [core.getInput(constants_1.Inputs.Path, { required: true })].concat(compressionMethod == constants_1.CompressionMethod.Zstd ? [compressionMethod] : []);
|
const components = [core.getInput(constants_1.Inputs.Path, { required: true })].concat(compressionMethod == constants_1.CompressionMethod.Zstd ? [compressionMethod] : []);
|
||||||
// Add salt to cache version to support breaking changes in cache entry
|
// Add salt to cache version to support breaking changes in cache entry
|
||||||
|
@ -2278,14 +2285,16 @@ function pipeResponseToStream(response, output) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function downloadCache(archiveLocation, archivePath) {
|
function downloadCache(archiveLocation, archivePath) {
|
||||||
|
var _a;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const stream = fs.createWriteStream(archivePath);
|
const stream = fs.createWriteStream(archivePath);
|
||||||
const httpClient = new http_client_1.HttpClient("actions/cache");
|
const httpClient = new http_client_1.HttpClient("actions/cache");
|
||||||
const downloadResponse = yield httpClient.get(archiveLocation);
|
const downloadResponse = yield httpClient.get(archiveLocation);
|
||||||
// Abort download if no traffic received over the socket.
|
// Abort download if no traffic received over the socket.
|
||||||
downloadResponse.message.socket.setTimeout(constants_1.SocketTimeout, () => {
|
const socketTimeout = (_a = parseEnvNumber("CACHE_SOCKET_TIMEOUT"), (_a !== null && _a !== void 0 ? _a : constants_1.DefaultSocketTimeout));
|
||||||
|
downloadResponse.message.socket.setTimeout(socketTimeout, () => {
|
||||||
downloadResponse.message.destroy();
|
downloadResponse.message.destroy();
|
||||||
core.debug(`Aborting download, socket timed out after ${constants_1.SocketTimeout} ms`);
|
core.debug(`Aborting download, socket timed out after ${socketTimeout} ms`);
|
||||||
});
|
});
|
||||||
yield pipeResponseToStream(downloadResponse, stream);
|
yield pipeResponseToStream(downloadResponse, stream);
|
||||||
// Validate download size.
|
// Validate download size.
|
||||||
|
@ -2352,13 +2361,6 @@ function uploadChunk(httpClient, resourceUrl, data, start, end) {
|
||||||
throw new Error(`Cache service responded with ${response.message.statusCode} during chunk upload.`);
|
throw new Error(`Cache service responded with ${response.message.statusCode} during chunk upload.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function parseEnvNumber(key) {
|
|
||||||
const value = Number(process.env[key]);
|
|
||||||
if (Number.isNaN(value) || value < 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
function uploadFile(httpClient, cacheId, archivePath) {
|
function uploadFile(httpClient, cacheId, archivePath) {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
@ -3642,6 +3644,12 @@ class HttpClientResponse {
|
||||||
this.message.on('data', (chunk) => {
|
this.message.on('data', (chunk) => {
|
||||||
output = Buffer.concat([output, chunk]);
|
output = Buffer.concat([output, chunk]);
|
||||||
});
|
});
|
||||||
|
this.message.on('aborted', () => {
|
||||||
|
reject("Request was aborted or closed prematurely");
|
||||||
|
});
|
||||||
|
this.message.on('timeout', (socket) => {
|
||||||
|
reject("Request timed out");
|
||||||
|
});
|
||||||
this.message.on('end', () => {
|
this.message.on('end', () => {
|
||||||
resolve(output.toString());
|
resolve(output.toString());
|
||||||
});
|
});
|
||||||
|
@ -3763,6 +3771,7 @@ class HttpClient {
|
||||||
let response;
|
let response;
|
||||||
while (numTries < maxTries) {
|
while (numTries < maxTries) {
|
||||||
response = await this.requestRaw(info, data);
|
response = await this.requestRaw(info, data);
|
||||||
|
|
||||||
// Check if it's an authentication challenge
|
// Check if it's an authentication challenge
|
||||||
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
|
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
|
||||||
let authenticationHandler;
|
let authenticationHandler;
|
||||||
|
@ -3874,6 +3883,7 @@ class HttpClient {
|
||||||
req.on('error', function (err) {
|
req.on('error', function (err) {
|
||||||
// err has statusCode property
|
// err has statusCode property
|
||||||
// res should have headers
|
// res should have headers
|
||||||
|
console.log(`Caught error on request: ${err}`);
|
||||||
handleResult(err, null);
|
handleResult(err, null);
|
||||||
});
|
});
|
||||||
if (data && typeof (data) === 'string') {
|
if (data && typeof (data) === 'string') {
|
||||||
|
@ -4628,7 +4638,7 @@ var CompressionMethod;
|
||||||
// Socket timeout in milliseconds during download. If no traffic is received
|
// Socket timeout in milliseconds during download. If no traffic is received
|
||||||
// over the socket during this period, the socket is destroyed and the download
|
// over the socket during this period, the socket is destroyed and the download
|
||||||
// is aborted.
|
// is aborted.
|
||||||
exports.SocketTimeout = 5000;
|
exports.DefaultSocketTimeout = 5000;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as fs from "fs";
|
||||||
import * as stream from "stream";
|
import * as stream from "stream";
|
||||||
import * as util from "util";
|
import * as util from "util";
|
||||||
|
|
||||||
import { CompressionMethod, Inputs, SocketTimeout } from "./constants";
|
import { CompressionMethod, DefaultSocketTimeout, Inputs } from "./constants";
|
||||||
import {
|
import {
|
||||||
ArtifactCacheEntry,
|
ArtifactCacheEntry,
|
||||||
CacheOptions,
|
CacheOptions,
|
||||||
|
@ -85,6 +85,14 @@ function createHttpClient(): HttpClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseEnvNumber(key: string): number | undefined {
|
||||||
|
const value = Number(process.env[key]);
|
||||||
|
if (Number.isNaN(value) || value < 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
export function getCacheVersion(compressionMethod?: CompressionMethod): string {
|
export function getCacheVersion(compressionMethod?: CompressionMethod): string {
|
||||||
const components = [core.getInput(Inputs.Path, { required: true })].concat(
|
const components = [core.getInput(Inputs.Path, { required: true })].concat(
|
||||||
compressionMethod == CompressionMethod.Zstd ? [compressionMethod] : []
|
compressionMethod == CompressionMethod.Zstd ? [compressionMethod] : []
|
||||||
|
@ -148,10 +156,12 @@ export async function downloadCache(
|
||||||
const downloadResponse = await httpClient.get(archiveLocation);
|
const downloadResponse = await httpClient.get(archiveLocation);
|
||||||
|
|
||||||
// Abort download if no traffic received over the socket.
|
// Abort download if no traffic received over the socket.
|
||||||
downloadResponse.message.socket.setTimeout(SocketTimeout, () => {
|
const socketTimeout =
|
||||||
|
parseEnvNumber("CACHE_SOCKET_TIMEOUT") ?? DefaultSocketTimeout;
|
||||||
|
downloadResponse.message.socket.setTimeout(socketTimeout, () => {
|
||||||
downloadResponse.message.destroy();
|
downloadResponse.message.destroy();
|
||||||
core.debug(
|
core.debug(
|
||||||
`Aborting download, socket timed out after ${SocketTimeout} ms`
|
`Aborting download, socket timed out after ${socketTimeout} ms`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -252,14 +262,6 @@ async function uploadChunk(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEnvNumber(key: string): number | undefined {
|
|
||||||
const value = Number(process.env[key]);
|
|
||||||
if (Number.isNaN(value) || value < 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadFile(
|
async function uploadFile(
|
||||||
httpClient: HttpClient,
|
httpClient: HttpClient,
|
||||||
cacheId: number,
|
cacheId: number,
|
||||||
|
|
|
@ -32,4 +32,4 @@ export enum CompressionMethod {
|
||||||
// Socket timeout in milliseconds during download. If no traffic is received
|
// Socket timeout in milliseconds during download. If no traffic is received
|
||||||
// over the socket during this period, the socket is destroyed and the download
|
// over the socket during this period, the socket is destroyed and the download
|
||||||
// is aborted.
|
// is aborted.
|
||||||
export const SocketTimeout = 5000;
|
export const DefaultSocketTimeout = 5000;
|
||||||
|
|
Loading…
Reference in New Issue