Skip to content

Commit

Permalink
Add option to adjust perform cache timeout in AbstractProvider.
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Jun 14, 2023
1 parent 84375be commit de0f518
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
31 changes: 29 additions & 2 deletions src.ts/providers/abstract-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,24 @@ type _PerformAccountRequest = {
method: "getStorage", position: bigint
}

/**
* Options for configuring some internal aspects of an [[AbstractProvider]].
*
* **``cacheTimeout``** - how long to cache a low-level ``_perform``
* for, based on input parameters. This reduces the number of calls
* to getChainId and getBlockNumber, but may break test chains which
* can perform operations (internally) synchronously. Use ``-1`` to
* disable, ``0`` will only buffer within the same event loop and
* any other value is in ms. (default: ``250``)
*/
export type AbstractProviderOptions = {
cacheTimeout?: number;
};

const defaultOptions = {
cacheTimeout: 250
};

type CcipArgs = {
sender: string;
urls: Array<string>;
Expand Down Expand Up @@ -436,12 +454,15 @@ export class AbstractProvider implements Provider {

#disableCcipRead: boolean;

#options: Required<AbstractProviderOptions>;

/**
* Create a new **AbstractProvider** connected to %%network%%, or
* use the various network detection capabilities to discover the
* [[Network]] if necessary.
*/
constructor(_network?: "any" | Networkish) {
constructor(_network?: "any" | Networkish, options?: AbstractProviderOptions) {
this.#options = Object.assign({ }, defaultOptions, options || { });

if (_network === "any") {
this.#anyNetwork = true;
Expand Down Expand Up @@ -512,19 +533,25 @@ export class AbstractProvider implements Provider {

// Shares multiple identical requests made during the same 250ms
async #perform<T = any>(req: PerformActionRequest): Promise<T> {
const timeout = this.#options.cacheTimeout;

// Caching disabled
if (timeout < 0) { return await this._perform(req); }

// Create a tag
const tag = getTag(req.method, req);

let perform = this.#performCache.get(tag);
if (!perform) {
perform = this._perform(req);

this.#performCache.set(tag, perform);

setTimeout(() => {
if (this.#performCache.get(tag) === perform) {
this.#performCache.delete(tag);
}
}, 250);
}, timeout);
}

return await perform;
Expand Down
16 changes: 13 additions & 3 deletions src.ts/providers/provider-jsonrpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { PollingEventSubscriber } from "./subscriber-polling.js";
import type { TypedDataDomain, TypedDataField } from "../hash/index.js";
import type { TransactionLike } from "../transaction/index.js";

import type { PerformActionRequest, Subscriber, Subscription } from "./abstract-provider.js";
import type { AbstractProviderOptions, PerformActionRequest, Subscriber, Subscription } from "./abstract-provider.js";
import type { Networkish } from "./network.js";
import type { Provider, TransactionRequest, TransactionResponse } from "./provider.js";
import type { Signer } from "./signer.js";
Expand Down Expand Up @@ -185,13 +185,17 @@ export type DebugEventJsonRpcApiProvider = {
*
* **``batchMaxCount``** - maximum number of requests to allow in a batch.
* If ``batchMaxCount = 1``, then batching is disabled. (default: ``100``)
*
* **``cacheTimeout``** - passed as [[AbstractProviderOptions]].
*/
export type JsonRpcApiProviderOptions = {
polling?: boolean;
staticNetwork?: null | Network;
batchStallTime?: number;
batchMaxSize?: number;
batchMaxCount?: number;

cacheTimeout?: number;
};

const defaultOptions = {
Expand All @@ -200,7 +204,9 @@ const defaultOptions = {

batchStallTime: 10, // 10ms
batchMaxSize: (1 << 20), // 1Mb
batchMaxCount: 100 // 100 requests
batchMaxCount: 100, // 100 requests

cacheTimeout: 250
}

/**
Expand Down Expand Up @@ -537,7 +543,11 @@ export abstract class JsonRpcApiProvider extends AbstractProvider {
}

constructor(network?: Networkish, options?: JsonRpcApiProviderOptions) {
super(network);
const superOptions: AbstractProviderOptions = { };
if (options && options.cacheTimeout != null) {
superOptions.cacheTimeout = options.cacheTimeout;
}
super(network, superOptions);

this.#nextId = 1;
this.#options = Object.assign({ }, defaultOptions, options || { });
Expand Down

0 comments on commit de0f518

Please # to comment.