Skip to content

Commit

Permalink
Added more robust poll event to Provider.
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed May 5, 2020
1 parent 86670eb commit dc48bfb
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 14 deletions.
3 changes: 2 additions & 1 deletion packages/ethers/src.ts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { Bytes, BytesLike, Hexable } from "@ethersproject/bytes"
import { Mnemonic } from "@ethersproject/hdnode";
import { EncryptOptions, ProgressCallback } from "@ethersproject/json-wallets";
import { Utf8ErrorFunc } from "@ethersproject/strings";
import { ConnectionInfo, FetchJsonResponse, OnceBlockable, PollOptions } from "@ethersproject/web";
import { ConnectionInfo, FetchJsonResponse, OnceBlockable, OncePollable, PollOptions } from "@ethersproject/web";

////////////////////////
// Exports
Expand Down Expand Up @@ -184,6 +184,7 @@ export {

ConnectionInfo,
OnceBlockable,
OncePollable,
PollOptions,
FetchJsonResponse,

Expand Down
52 changes: 39 additions & 13 deletions packages/providers/src.ts/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ function getTime() {
/**
* EventType
* - "block"
* - "poll"
* - "pending"
* - "error"
* - filter
Expand Down Expand Up @@ -164,7 +165,7 @@ export class Event {
}

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");
}
}

Expand Down Expand Up @@ -196,6 +197,7 @@ export class BaseProvider extends Provider {

_pollingInterval: number;
_poller: NodeJS.Timer;
_bootstrapPoll: NodeJS.Timer;

_lastBlockNumber: number;

Expand Down Expand Up @@ -328,17 +330,23 @@ export class BaseProvider extends Provider {

async poll(): Promise<void> {
const pollId = nextPollId++;

this.emit("willPoll", pollId);

// Track all running promises, so we can trigger a post-poll once they are complete
const runners: Array<Promise<void>> = [];

const blockNumber = await this._getInternalBlockNumber(100 + this.pollingInterval / 2);

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 (blockNumber === this._lastBlockNumber) { return; }
if (blockNumber === this._lastBlockNumber) {
this.emit("didPoll", pollId);
return;
}

// First polling cycle, trigger a "block" events
if (this._emitted.block === -2) {
Expand Down Expand Up @@ -439,24 +447,42 @@ export class BaseProvider extends Provider {
}

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 {
return (this._poller != null);
}

set polling(value: boolean) {
setTimeout(() => {
if (value && !this._poller) {
this._poller = setInterval(this.poll.bind(this), this.pollingInterval);
this.poll();

} else if (!value && this._poller) {
clearInterval(this._poller);
this._poller = null;
if (value && !this._poller) {
this._poller = setInterval(this.poll.bind(this), this.pollingInterval);

if (!this._bootstrapPoll) {
this._bootstrapPoll = setTimeout(() => {
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 {
Expand Down
8 changes: 8 additions & 0 deletions packages/web/src.ts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ export interface OnceBlockable {
once(eventName: "block", handler: () => void): void;
}

export interface OncePollable {
once(eventName: "poll", handler: () => void): void;
}

export type PollOptions = {
timeout?: number,
floor?: number,
ceiling?: number,
interval?: number,
retryLimit?: number,
onceBlock?: OnceBlockable
oncePoll?: OncePollable
};

export type FetchJsonResponse = {
Expand Down Expand Up @@ -230,6 +235,9 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
if (result !== undefined) {
if (cancel()) { resolve(result); }

} else if (options.oncePoll) {
options.oncePoll.once("poll", check);

} else if (options.onceBlock) {
options.onceBlock.once("block", check);

Expand Down

0 comments on commit dc48bfb

Please sign in to comment.