Add env var for socket timeout

This commit is contained in:
Dave Hadka 2020-05-07 21:35:11 -04:00
parent ce9276c90e
commit 18e62e1fe0
4 changed files with 54 additions and 32 deletions

30
dist/restore/index.js vendored

@ -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;
/***/ }), /***/ }),

30
dist/save/index.js vendored

@ -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;