-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: pre-emptive stream creation for protocols (#1516)
* pass log as an arg to baseprotocol * optimistically create and use streams for light protocols * refactor BaseProtocol for readability * use optimistic stream selection in protocols * use a new stream for every request instead of reusing * replenish streams correctly * create StreamManager * refactor for a single stream * fix: listener binds * declare streamManager as a class var isntead of extending * remove stream destruction as it happens by default * simplify logic & address comments * fix: bind typo * refactor for improvements * fix typedoc * rm: lock * restructure StreamManager for readbility * remove log as an arg * use newStream as a facade in BaseProtoocl
- Loading branch information
1 parent
1c09092
commit b4f8216
Showing
7 changed files
with
89 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import type { PeerUpdate } from "@libp2p/interface"; | ||
import type { Stream } from "@libp2p/interface/connection"; | ||
import { Peer } from "@libp2p/interface/peer-store"; | ||
import { Libp2p } from "@waku/interfaces"; | ||
import { selectConnection } from "@waku/utils/libp2p"; | ||
import debug from "debug"; | ||
|
||
export class StreamManager { | ||
private streamPool: Map<string, Promise<Stream>>; | ||
private log: debug.Debugger; | ||
|
||
constructor( | ||
public multicodec: string, | ||
public getConnections: Libp2p["getConnections"], | ||
public addEventListener: Libp2p["addEventListener"] | ||
) { | ||
this.log = debug(`waku:stream-manager:${multicodec}`); | ||
this.addEventListener( | ||
"peer:update", | ||
this.handlePeerUpdateStreamPool.bind(this) | ||
); | ||
this.getStream = this.getStream.bind(this); | ||
this.streamPool = new Map(); | ||
} | ||
|
||
public async getStream(peer: Peer): Promise<Stream> { | ||
const peerIdStr = peer.id.toString(); | ||
const streamPromise = this.streamPool.get(peerIdStr); | ||
|
||
if (!streamPromise) { | ||
return this.newStream(peer); // fallback by creating a new stream on the spot | ||
} | ||
|
||
// We have the stream, let's remove it from the map | ||
this.streamPool.delete(peerIdStr); | ||
|
||
this.prepareNewStream(peer); | ||
|
||
const stream = await streamPromise; | ||
|
||
if (stream.status === "closed") { | ||
return this.newStream(peer); // fallback by creating a new stream on the spot | ||
} | ||
|
||
return stream; | ||
} | ||
|
||
private async newStream(peer: Peer): Promise<Stream> { | ||
const connections = this.getConnections(peer.id); | ||
const connection = selectConnection(connections); | ||
if (!connection) { | ||
throw new Error("Failed to get a connection to the peer"); | ||
} | ||
return connection.newStream(this.multicodec); | ||
} | ||
|
||
private prepareNewStream(peer: Peer): void { | ||
const streamPromise = this.newStream(peer); | ||
this.streamPool.set(peer.id.toString(), streamPromise); | ||
} | ||
|
||
private handlePeerUpdateStreamPool = (evt: CustomEvent<PeerUpdate>): void => { | ||
const peer = evt.detail.peer; | ||
if (peer.protocols.includes(this.multicodec)) { | ||
this.log(`Optimistically opening a stream to ${peer.id.toString()}`); | ||
this.prepareNewStream(peer); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters