Add option to adjust perform cache timeout in AbstractProvider.

This commit is contained in:
Richard Moore 2023-06-13 21:40:26 -04:00
parent 84375be92d
commit de0f5189f6
2 changed files with 42 additions and 5 deletions

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

@ -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";
@ -185,6 +185,8 @@ 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;
@ -192,6 +194,8 @@ export type JsonRpcApiProviderOptions = {
batchStallTime?: number;
batchMaxSize?: number;
batchMaxCount?: number;
cacheTimeout?: number;
};
const defaultOptions = {
@ -200,7 +204,9 @@ const defaultOptions = {
batchStallTime: 10, // 10ms
batchMaxSize: (1 << 20), // 1Mb
batchMaxCount: 100 // 100 requests
batchMaxCount: 100, // 100 requests
cacheTimeout: 250
}
/**
@ -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 || { });