Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Upgrade undici and make sure to always set its timeout fields #3665

Closed
wants to merge 8 commits into from
5 changes: 5 additions & 0 deletions .changeset/fresh-rings-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomiclabs/hardhat-vyper": patch
---

Increase the timeout used to download the compiler
6 changes: 6 additions & 0 deletions .changeset/loud-kiwis-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@nomiclabs/hardhat-etherscan": patch
"hardhat": patch
---

Fix how HTTP timeouts are handled
2 changes: 1 addition & 1 deletion packages/hardhat-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"source-map-support": "^0.5.13",
"stacktrace-parser": "^0.1.10",
"tsort": "0.0.1",
"undici": "^5.14.0",
"undici": "^5.18.0",
"uuid": "^8.3.2",
"ws": "^7.4.6"
},
Expand Down
48 changes: 33 additions & 15 deletions packages/hardhat-core/src/internal/core/providers/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
private readonly _url: string,
private readonly _networkName: string,
private readonly _extraHeaders: { [name: string]: string } = {},
private readonly _timeout = 20000,
timeout = 20000,
client: Undici.Dispatcher | undefined = undefined
) {
super();
Expand All @@ -59,10 +59,24 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
"utf-8"
).toString("base64")}`;
try {
this._dispatcher = client ?? new Pool(url.origin);
if (process.env.DO_NOT_SET_THIS_ENV_VAR____IS_HARDHAT_CI !== undefined) {
timeout = 0;
}

const options: Undici.Agent.Options = {
connections: 128, // We sate a sane limit of concurrent connections
connect: { timeout },
bodyTimeout: timeout,
headersTimeout: timeout,
};

if (process.env.http_proxy !== undefined && shouldUseProxy(url.origin)) {
this._dispatcher = new ProxyAgent(process.env.http_proxy);
this._dispatcher = new ProxyAgent({
uri: process.env.http_proxy,
...options,
});
} else {
this._dispatcher = client ?? new Pool(url.origin, options);
}
} catch (e) {
if (e instanceof TypeError && e.message === "Invalid URL") {
Expand Down Expand Up @@ -171,22 +185,23 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
const { request: sendRequest } = await import("undici");
const url = new URL(this._url);

const headers: { [name: string]: string } = {
"Content-Type": "application/json",
"User-Agent": `hardhat ${hardhatVersion}`,
...this._extraHeaders,
};

if (this._authHeader !== undefined) {
headers.Authorization = this._authHeader;
}

try {
const response = await sendRequest(url, {
dispatcher: this._dispatcher,
method: "POST",
body: JSON.stringify(request),
maxRedirections: 10,
headersTimeout:
process.env.DO_NOT_SET_THIS_ENV_VAR____IS_HARDHAT_CI !== undefined
? 0
: this._timeout,
headers: {
"Content-Type": "application/json",
"User-Agent": `hardhat ${hardhatVersion}`,
Authorization: this._authHeader,
...this._extraHeaders,
},
headers,
});

if (this._isRateLimitResponse(response)) {
Expand Down Expand Up @@ -219,7 +234,10 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
);
}

if (error.type === "request-timeout") {
if (
typeof error.code === "string" &&
error.code.endsWith("_TIMEOUT") === true
) {
throw new HardhatError(ERRORS.NETWORK.NETWORK_TIMEOUT, {}, error);
}

Expand Down Expand Up @@ -270,7 +288,7 @@ export class HttpProvider extends EventEmitter implements EIP1193Provider {
): number | undefined {
const header = response.headers["retry-after"];

if (header === undefined || header === null) {
if (header === undefined || header === null || Array.isArray(header)) {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ export class JsonRpcServer implements IJsonRpcServer {
this._wsServer.on("connection", handler.handleWs);
}

// NOTE: This method is only used for testing
public getProvider = (name = "json-rpc"): EIP1193Provider => {
const { Client } = require("undici") as { Client: typeof ClientT };
const { address, port } = this._httpServer.address() as AddressInfo;

// NOTE: These timeouts are extremelly low because this method is only used for testing.
const dispatcher = new Client(`http://${address}:${port}/`, {
keepAliveTimeout: 10,
keepAliveMaxTimeout: 10,
Expand Down
1 change: 1 addition & 0 deletions packages/hardhat-core/src/internal/util/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export async function download(
const response = await request(url, {
dispatcher,
headersTimeout: timeoutMillis,
bodyTimeout: timeoutMillis,
maxRedirections: 10,
method: "GET",
headers: {
Expand Down
2 changes: 1 addition & 1 deletion packages/hardhat-docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@
"dependencies": {
"dockerode": "^2.5.8",
"fs-extra": "^7.0.1",
"undici": "^5.14.0"
"undici": "^5.18.0"
}
}
2 changes: 1 addition & 1 deletion packages/hardhat-etherscan/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"lodash": "^4.17.11",
"semver": "^6.3.0",
"table": "^6.8.0",
"undici": "^5.14.0"
"undici": "^5.18.0"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/hardhat-vyper/src/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { VyperPluginError, getLogger } from "./util";

const log = getLogger("downloader");

const DOWNLOAD_TIMEOUT_MS = 30_000;
const DOWNLOAD_TIMEOUT_MS = 40_000;

async function downloadFile(
url: string,
Expand Down
Loading