Skip to content

Commit

Permalink
fix: reduce Connection keep-alive timeout to 1 second fewer than the …
Browse files Browse the repository at this point in the history
…Solana RPC's keep-alive timeout (#29130)

* Delete `AgentManager`

* Replace custom `http.Agent` implementation with `agentkeepalive` package

* Set the default free socket timeout to 1s less than the Solana RPC's default timeout

* Add link to particular issue comment

* Create the correct flavor of default agent for http/https
  • Loading branch information
steveluscher committed Dec 19, 2022
1 parent 3eca364 commit 456a819
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 102 deletions.
1 change: 1 addition & 0 deletions web3.js/package.json
Expand Up @@ -62,6 +62,7 @@
"@noble/hashes": "^1.1.2",
"@noble/secp256k1": "^1.6.3",
"@solana/buffer-layout": "^4.0.0",
"agentkeepalive": "^4.2.1",
"bigint-buffer": "^1.1.5",
"bn.js": "^5.0.0",
"borsh": "^0.7.0",
Expand Down
44 changes: 0 additions & 44 deletions web3.js/src/agent-manager.ts

This file was deleted.

40 changes: 23 additions & 17 deletions web3.js/src/connection.ts
@@ -1,9 +1,12 @@
import HttpKeepAliveAgent, {
HttpsAgent as HttpsKeepAliveAgent,
} from 'agentkeepalive';
import bs58 from 'bs58';
import {Buffer} from 'buffer';
// @ts-ignore
import fastStableStringify from 'fast-stable-stringify';
import type {Agent as HttpAgent} from 'http';
import {Agent as HttpsAgent} from 'https';
import type {Agent as NodeHttpAgent} from 'http';
import {Agent as NodeHttpsAgent} from 'https';
import {
type as pick,
number,
Expand All @@ -27,7 +30,6 @@ import {Client as RpcWebSocketClient} from 'rpc-websockets';
import RpcClient from 'jayson/lib/client/browser';
import {JSONRPCError} from 'jayson';

import {AgentManager} from './agent-manager';
import {EpochSchedule} from './epoch-schedule';
import {SendTransactionError, SolanaJSONRPCError} from './errors';
import fetchImpl, {Response} from './fetch-impl';
Expand Down Expand Up @@ -1452,12 +1454,10 @@ function createRpcClient(
customFetch?: FetchFn,
fetchMiddleware?: FetchMiddleware,
disableRetryOnRateLimit?: boolean,
httpAgent?: HttpAgent | HttpsAgent | false,
httpAgent?: NodeHttpAgent | NodeHttpsAgent | false,
): RpcClient {
const fetch = customFetch ? customFetch : fetchImpl;
let agentManager:
| {requestEnd(): void; requestStart(): HttpAgent | HttpsAgent}
| undefined;
let agent: NodeHttpAgent | NodeHttpsAgent | undefined;
if (process.env.BROWSER) {
if (httpAgent != null) {
console.warn(
Expand All @@ -1468,29 +1468,38 @@ function createRpcClient(
} else {
if (httpAgent == null) {
if (process.env.NODE_ENV !== 'test') {
agentManager = new AgentManager(
url.startsWith('https:') /* useHttps */,
);
const agentOptions = {
// One second fewer than the Solana RPC's keepalive timeout.
// Read more: https://github.com/solana-labs/solana/issues/27859#issuecomment-1340097889
freeSocketTimeout: 19000,
keepAlive: true,
maxSockets: 25,
};
if (url.startsWith('https:')) {
agent = new HttpsKeepAliveAgent(agentOptions);
} else {
agent = new HttpKeepAliveAgent(agentOptions);
}
}
} else {
if (httpAgent !== false) {
const isHttps = url.startsWith('https:');
if (isHttps && !(httpAgent instanceof HttpsAgent)) {
if (isHttps && !(httpAgent instanceof NodeHttpsAgent)) {
throw new Error(
'The endpoint `' +
url +
'` can only be paired with an `https.Agent`. You have, instead, supplied an ' +
'`http.Agent` through `httpAgent`.',
);
} else if (!isHttps && httpAgent instanceof HttpsAgent) {
} else if (!isHttps && httpAgent instanceof NodeHttpsAgent) {
throw new Error(
'The endpoint `' +
url +
'` can only be paired with an `http.Agent`. You have, instead, supplied an ' +
'`https.Agent` through `httpAgent`.',
);
}
agentManager = {requestEnd() {}, requestStart: () => httpAgent};
agent = httpAgent;
}
}
}
Expand All @@ -1515,7 +1524,6 @@ function createRpcClient(
}

const clientBrowser = new RpcClient(async (request, callback) => {
const agent = agentManager ? agentManager.requestStart() : undefined;
const options = {
method: 'POST',
body: request,
Expand Down Expand Up @@ -1565,8 +1573,6 @@ function createRpcClient(
}
} catch (err) {
if (err instanceof Error) callback(err);
} finally {
agentManager && agentManager.requestEnd();
}
}, {});

Expand Down Expand Up @@ -2898,7 +2904,7 @@ export type ConnectionConfig = {
* persistence). Set this to `false` to create a connection that uses no agent. This applies to
* Node environments only.
*/
httpAgent?: HttpAgent | HttpsAgent | false;
httpAgent?: NodeHttpAgent | NodeHttpsAgent | false;
/** Optional commitment level */
commitment?: Commitment;
/** Optional endpoint URL to the fullnode JSON RPC PubSub WebSocket Endpoint */
Expand Down
40 changes: 0 additions & 40 deletions web3.js/test/agent-manager.test.ts

This file was deleted.

11 changes: 10 additions & 1 deletion web3.js/yarn.lock
Expand Up @@ -1834,14 +1834,23 @@ agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2:
dependencies:
debug "4"

agentkeepalive@^4.1.3, agentkeepalive@^4.2.1:
agentkeepalive@^4.1.3:
version "4.2.1"
resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz"
dependencies:
debug "^4.1.0"
depd "^1.1.2"
humanize-ms "^1.2.1"

agentkeepalive@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717"
integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==
dependencies:
debug "^4.1.0"
depd "^1.1.2"
humanize-ms "^1.2.1"

aggregate-error@^3.0.0:
version "3.1.0"
resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz"
Expand Down

0 comments on commit 456a819

Please sign in to comment.