refactor: extract peer discovery static list

This commit is contained in:
fryorcraken.eth 2022-08-01 22:50:02 +10:00 committed by fryorcraken.eth
parent 731318fa66
commit 080357355b
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
3 changed files with 136 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import { PeerInfo } from "@libp2p/interface-peer-info";
import { peerIdFromString } from "@libp2p/peer-id";
import { Multiaddr } from "@multiformats/multiaddr";
export function multiaddrsToPeerInfo(mas: Multiaddr[]): PeerInfo[] {
return mas
.map((ma) => {
const peerIdStr = ma.getPeerId();
const protocols: string[] = [];
return {
id: peerIdStr ? peerIdFromString(peerIdStr) : null,
multiaddrs: [ma.decapsulateCode(421)],
protocols,
};
})
.filter((peerInfo): peerInfo is PeerInfo => peerInfo.id !== null);
}

View File

@ -0,0 +1,119 @@
import type {
PeerDiscovery,
PeerDiscoveryEvents,
} from "@libp2p/interface-peer-discovery";
import { symbol } from "@libp2p/interface-peer-discovery";
import type { PeerInfo } from "@libp2p/interface-peer-info";
import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
import { Multiaddr } from "@multiformats/multiaddr";
import debug from "debug";
import { multiaddrsToPeerInfo } from "./multiaddr_to_peer_info";
import { getPseudoRandomSubset } from "./random_subset";
const log = debug("waku:discovery:static-list");
export interface Options {
/**
* The maximum of peers to connect to as part of the bootstrap process.
*
* @default The length of the passed `peers` array.
*/
maxPeers?: number;
/**
* The interval between emitting addresses in milliseconds.
*
* @default {@link PeerDiscoveryEvents.DefaultInterval}
*/
interval?: number;
}
/**
* Parse options and expose function to return bootstrap peer addresses.
*
* @throws if an invalid combination of options is passed, see [[BootstrapOptions]] for details.
*/
export class PeerDiscoveryStaticPeers
extends EventEmitter<PeerDiscoveryEvents>
implements PeerDiscovery
{
static DefaultInterval = 200;
private readonly peers: PeerInfo[];
private timer?: ReturnType<typeof setInterval>;
private readonly interval: number;
/**
* @param peers Multiaddrs of peers to connect to.
* @param opts
*/
constructor(peers: string[] | Multiaddr[], opts?: Options) {
super();
this.interval = opts?.interval ?? PeerDiscoveryStaticPeers.DefaultInterval;
const maxPeers = opts?.maxPeers ?? peers?.length;
const peerMas = peers.map((peer: string | Multiaddr) => {
if (typeof peer === "string") {
return new Multiaddr(peer);
} else {
return peer;
}
});
this.peers = multiaddrsToPeerInfo(getPseudoRandomSubset(peerMas, maxPeers));
log(
"Use provided list of peers (reduced to maxPeers)",
this.peers.map((ma) => ma.toString())
);
}
/**
* Start emitting static peers.
*/
start(): void {
this._startTimer();
}
private _startTimer(): void {
if (this.peers) {
log("Starting emitting static peers for boostrap.");
if (this.timer != null) {
return;
}
this.timer = setInterval(() => this._returnPeers(), this.interval);
this._returnPeers();
}
}
_returnPeers(): void {
if (this.timer == null) {
return;
}
this.peers.forEach((peerData) => {
this.dispatchEvent(
new CustomEvent<PeerInfo>("peer", { detail: peerData })
);
});
}
/**
* Stop emitting peers.
*/
stop(): void {
if (this.timer != null) {
clearInterval(this.timer);
}
this.timer = undefined;
}
get [symbol](): true {
return true;
}
get [Symbol.toStringTag](): string {
return "@waku/peer-discovery-static-list";
}
}