Added more robust poll event to Provider.
This commit is contained in:
parent
86670eb80e
commit
dc48bfb7ad
@ -36,7 +36,7 @@ import { Bytes, BytesLike, Hexable } from "@ethersproject/bytes"
|
|||||||
import { Mnemonic } from "@ethersproject/hdnode";
|
import { Mnemonic } from "@ethersproject/hdnode";
|
||||||
import { EncryptOptions, ProgressCallback } from "@ethersproject/json-wallets";
|
import { EncryptOptions, ProgressCallback } from "@ethersproject/json-wallets";
|
||||||
import { Utf8ErrorFunc } from "@ethersproject/strings";
|
import { Utf8ErrorFunc } from "@ethersproject/strings";
|
||||||
import { ConnectionInfo, FetchJsonResponse, OnceBlockable, PollOptions } from "@ethersproject/web";
|
import { ConnectionInfo, FetchJsonResponse, OnceBlockable, OncePollable, PollOptions } from "@ethersproject/web";
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Exports
|
// Exports
|
||||||
@ -184,6 +184,7 @@ export {
|
|||||||
|
|
||||||
ConnectionInfo,
|
ConnectionInfo,
|
||||||
OnceBlockable,
|
OnceBlockable,
|
||||||
|
OncePollable,
|
||||||
PollOptions,
|
PollOptions,
|
||||||
FetchJsonResponse,
|
FetchJsonResponse,
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ function getTime() {
|
|||||||
/**
|
/**
|
||||||
* EventType
|
* EventType
|
||||||
* - "block"
|
* - "block"
|
||||||
|
* - "poll"
|
||||||
* - "pending"
|
* - "pending"
|
||||||
* - "error"
|
* - "error"
|
||||||
* - filter
|
* - filter
|
||||||
@ -164,7 +165,7 @@ export class Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pollable(): boolean {
|
pollable(): boolean {
|
||||||
return (this.tag.indexOf(":") >= 0 || this.tag === "block" || this.tag === "pending");
|
return (this.tag.indexOf(":") >= 0 || this.tag === "block" || this.tag === "pending" || this.tag === "poll");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +197,7 @@ export class BaseProvider extends Provider {
|
|||||||
|
|
||||||
_pollingInterval: number;
|
_pollingInterval: number;
|
||||||
_poller: NodeJS.Timer;
|
_poller: NodeJS.Timer;
|
||||||
|
_bootstrapPoll: NodeJS.Timer;
|
||||||
|
|
||||||
_lastBlockNumber: number;
|
_lastBlockNumber: number;
|
||||||
|
|
||||||
@ -328,17 +330,23 @@ export class BaseProvider extends Provider {
|
|||||||
|
|
||||||
async poll(): Promise<void> {
|
async poll(): Promise<void> {
|
||||||
const pollId = nextPollId++;
|
const pollId = nextPollId++;
|
||||||
|
|
||||||
this.emit("willPoll", pollId);
|
this.emit("willPoll", pollId);
|
||||||
|
|
||||||
// Track all running promises, so we can trigger a post-poll once they are complete
|
// Track all running promises, so we can trigger a post-poll once they are complete
|
||||||
const runners: Array<Promise<void>> = [];
|
const runners: Array<Promise<void>> = [];
|
||||||
|
|
||||||
const blockNumber = await this._getInternalBlockNumber(100 + this.pollingInterval / 2);
|
const blockNumber = await this._getInternalBlockNumber(100 + this.pollingInterval / 2);
|
||||||
|
|
||||||
this._setFastBlockNumber(blockNumber);
|
this._setFastBlockNumber(blockNumber);
|
||||||
|
|
||||||
|
// Emit a poll event after we have the latest (fast) block number
|
||||||
|
this.emit("poll", pollId, blockNumber);
|
||||||
|
|
||||||
// If the block has not changed, meh.
|
// If the block has not changed, meh.
|
||||||
if (blockNumber === this._lastBlockNumber) { return; }
|
if (blockNumber === this._lastBlockNumber) {
|
||||||
|
this.emit("didPoll", pollId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// First polling cycle, trigger a "block" events
|
// First polling cycle, trigger a "block" events
|
||||||
if (this._emitted.block === -2) {
|
if (this._emitted.block === -2) {
|
||||||
@ -439,7 +447,11 @@ export class BaseProvider extends Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get blockNumber(): number {
|
get blockNumber(): number {
|
||||||
return this._fastBlockNumber;
|
this._getInternalBlockNumber(100 + this.pollingInterval / 2).then((blockNumber) => {
|
||||||
|
this._setFastBlockNumber(blockNumber);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (this._fastBlockNumber != null) ? this._fastBlockNumber: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
get polling(): boolean {
|
get polling(): boolean {
|
||||||
@ -447,16 +459,30 @@ export class BaseProvider extends Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set polling(value: boolean) {
|
set polling(value: boolean) {
|
||||||
setTimeout(() => {
|
if (value && !this._poller) {
|
||||||
if (value && !this._poller) {
|
this._poller = setInterval(this.poll.bind(this), this.pollingInterval);
|
||||||
this._poller = setInterval(this.poll.bind(this), this.pollingInterval);
|
|
||||||
this.poll();
|
|
||||||
|
|
||||||
} else if (!value && this._poller) {
|
if (!this._bootstrapPoll) {
|
||||||
clearInterval(this._poller);
|
this._bootstrapPoll = setTimeout(() => {
|
||||||
this._poller = null;
|
this.poll();
|
||||||
|
|
||||||
|
// We block additional polls until the polling interval
|
||||||
|
// is done, to prevent overwhelming the poll function
|
||||||
|
this._bootstrapPoll = setTimeout(() => {
|
||||||
|
// If polling was disabled, something may require a poke
|
||||||
|
// since starting the bootstrap poll and it was disabled
|
||||||
|
if (!this._poller) { this.poll(); }
|
||||||
|
|
||||||
|
// Clear out the bootstrap so we can do another
|
||||||
|
this._bootstrapPoll = null;
|
||||||
|
}, this.pollingInterval);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}, 0);
|
|
||||||
|
} else if (!value && this._poller) {
|
||||||
|
clearInterval(this._poller);
|
||||||
|
this._poller = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get pollingInterval(): number {
|
get pollingInterval(): number {
|
||||||
|
@ -25,6 +25,10 @@ export interface OnceBlockable {
|
|||||||
once(eventName: "block", handler: () => void): void;
|
once(eventName: "block", handler: () => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OncePollable {
|
||||||
|
once(eventName: "poll", handler: () => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
export type PollOptions = {
|
export type PollOptions = {
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
floor?: number,
|
floor?: number,
|
||||||
@ -32,6 +36,7 @@ export type PollOptions = {
|
|||||||
interval?: number,
|
interval?: number,
|
||||||
retryLimit?: number,
|
retryLimit?: number,
|
||||||
onceBlock?: OnceBlockable
|
onceBlock?: OnceBlockable
|
||||||
|
oncePoll?: OncePollable
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FetchJsonResponse = {
|
export type FetchJsonResponse = {
|
||||||
@ -230,6 +235,9 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
|
|||||||
if (result !== undefined) {
|
if (result !== undefined) {
|
||||||
if (cancel()) { resolve(result); }
|
if (cancel()) { resolve(result); }
|
||||||
|
|
||||||
|
} else if (options.oncePoll) {
|
||||||
|
options.oncePoll.once("poll", check);
|
||||||
|
|
||||||
} else if (options.onceBlock) {
|
} else if (options.onceBlock) {
|
||||||
options.onceBlock.once("block", check);
|
options.onceBlock.once("block", check);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user