Skip to content

Commit 326d73d

Browse files
committed
chore: improve docs
1 parent 7ca7f06 commit 326d73d

File tree

4 files changed

+114
-6
lines changed

4 files changed

+114
-6
lines changed

README.md

+13-4
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ js-libp2p-pubsub
3232

3333
## Usage
3434

35-
Create your pubsub implementation extending the base protocol.
35+
A pubsub implementation **MUST** override the `_processConnection`, `publish`, `subscribe` and `unsubscribe` functions. `add_peer` and `remove_peer` may be overwritten if the pubsub implementation needs to add custom logic when peers are added and remove. All the remaining functions **MUST NOT** be overwritten.
36+
37+
The following example aims to show how to create your pubsub implementation extending this base protocol. The pubsub implementation will handle the subscriptions logic.
3638

3739
```JavaScript
3840
const Pubsub = require('libp2p-pubsub')
@@ -43,23 +45,30 @@ class PubsubImplementation extends Pubsub {
4345
}
4446

4547
_processConnection(idB58Str, conn, peer) {
48+
// Required to be implemented by the subclass
4649
// Process each message accordingly
4750
}
4851

4952
publish() {
50-
53+
// Required to be implemented by the subclass
5154
}
5255

5356
subscribe() {
54-
57+
// Required to be implemented by the subclass
5558
}
5659

5760
unsubscribe() {
58-
61+
// Required to be implemented by the subclass
5962
}
6063
}
6164
```
6265

66+
## Implementations using this base protocol
67+
68+
You can use the following implementations as examples for building your own pubsub implementation.
69+
70+
- [libp2p/js-libp2p-floodsub](https://github.com/libp2p/js-libp2p-floodsub)
71+
6372
## Contribute
6473

6574
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-pubsub/issues)!

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"dependencies": {
5858
"async": "^2.6.1",
5959
"debug": "^4.1.1",
60+
"err-code": "^1.1.2",
6061
"length-prefixed-stream": "^1.6.0",
6162
"protons": "^1.0.1",
6263
"pull-pushable": "^2.2.0"

src/index.js

+88-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ const EventEmitter = require('events')
44
const pull = require('pull-stream/pull')
55
const empty = require('pull-stream/sources/empty')
66
const asyncEach = require('async/each')
7+
78
const debug = require('debug')
9+
const errcode = require('err-code')
810

911
const Peer = require('./peer')
1012
const message = require('./message')
@@ -18,7 +20,7 @@ class PubsubBaseProtocol extends EventEmitter {
1820
/**
1921
* @param {String} debugName
2022
* @param {String} multicodec
21-
* @param {Object} libp2p
23+
* @param {Object} libp2p libp2p implementation
2224
* @constructor
2325
*/
2426
constructor (debugName, multicodec, libp2p) {
@@ -44,6 +46,12 @@ class PubsubBaseProtocol extends EventEmitter {
4446
this._dialPeer = this._dialPeer.bind(this)
4547
}
4648

49+
/**
50+
* Add a new connected peer to the peers map.
51+
* @private
52+
* @param {PeerInfo} peer peer info
53+
* @returns {PeerInfo}
54+
*/
4755
_addPeer (peer) {
4856
const id = peer.info.id.toB58String()
4957

@@ -67,6 +75,12 @@ class PubsubBaseProtocol extends EventEmitter {
6775
return existing
6876
}
6977

78+
/**
79+
* Remove a peer from the peers map if it has no references.
80+
* @private
81+
* @param {Peer} peer peer state
82+
* @returns {PeerInfo}
83+
*/
7084
_removePeer (peer) {
7185
const id = peer.info.id.toB58String()
7286

@@ -80,6 +94,13 @@ class PubsubBaseProtocol extends EventEmitter {
8094
return peer
8195
}
8296

97+
/**
98+
* Dial a received peer.
99+
* @private
100+
* @param {PeerInfo} peerInfo peer info
101+
* @param {function} callback
102+
* @returns {void}
103+
*/
83104
_dialPeer (peerInfo, callback) {
84105
callback = callback || function noop () { }
85106
const idB58Str = peerInfo.id.toB58String()
@@ -121,6 +142,13 @@ class PubsubBaseProtocol extends EventEmitter {
121142
})
122143
}
123144

145+
/**
146+
* Dial a received peer.
147+
* @private
148+
* @param {PeerInfo} peerInfo peer info
149+
* @param {Connection} conn connection to the peer
150+
* @param {function} callback
151+
*/
124152
_onDial (peerInfo, conn, callback) {
125153
const idB58Str = peerInfo.id.toB58String()
126154
this.log('connected', idB58Str)
@@ -131,6 +159,12 @@ class PubsubBaseProtocol extends EventEmitter {
131159
nextTick(() => callback())
132160
}
133161

162+
/**
163+
* On successful connection event.
164+
* @private
165+
* @param {String} protocol connection protocol
166+
* @param {Connection} conn connection to the peer
167+
*/
134168
_onConnection (protocol, conn) {
135169
conn.getPeerInfo((err, peerInfo) => {
136170
if (err) {
@@ -145,10 +179,27 @@ class PubsubBaseProtocol extends EventEmitter {
145179
})
146180
}
147181

182+
/**
183+
* Overriding the implementation of _processConnection should keep the connection and is
184+
* responsible for processing each RPC message received by other peers.
185+
* @abstract
186+
* @param {string} idB58Str peer id string in base58
187+
* @param {Connection} conn connection
188+
* @param {PeerInfo} peer peer info
189+
* @returns {undefined}
190+
*
191+
*/
148192
_processConnection (idB58Str, conn, peer) {
149-
throw new Error('_processConnection must be implemented by the subclass')
193+
throw errcode('_processConnection must be implemented by the subclass', 'ERR_NOT_IMPLEMENTED')
150194
}
151195

196+
/**
197+
* On connection end event.
198+
* @private
199+
* @param {string} idB58Str peer id string in base58
200+
* @param {PeerInfo} peer peer info
201+
* @param {Error} err error for connection end
202+
*/
152203
_onConnectionEnd (idB58Str, peer, err) {
153204
// socket hang up, means the one side canceled
154205
if (err && err.message !== 'socket hang up') {
@@ -159,6 +210,41 @@ class PubsubBaseProtocol extends EventEmitter {
159210
this._removePeer(peer)
160211
}
161212

213+
/**
214+
* Overriding the implementation of publish should handle the appropriate algorithms for the publish/subscriber implementation.
215+
* For example, a Floodsub implementation might simply publish each message to each topic for every peer
216+
* @abstract
217+
* @param {Array<string>|string} topics
218+
* @param {Array<any>|any} messages
219+
* @returns {undefined}
220+
*
221+
*/
222+
publish (topics, messages) {
223+
throw errcode('publish must be implemented by the subclass', 'ERR_NOT_IMPLEMENTED')
224+
}
225+
226+
/**
227+
* Overriding the implementation of subscribe should handle the appropriate algorithms for the publish/subscriber implementation.
228+
* For example, a Floodsub implementation might simply send a message for every peer showing interest in the topics
229+
* @abstract
230+
* @param {Array<string>|string} topics
231+
* @returns {undefined}
232+
*/
233+
subscribe (topics) {
234+
throw errcode('subscribe must be implemented by the subclass', 'ERR_NOT_IMPLEMENTED')
235+
}
236+
237+
/**
238+
* Overriding the implementation of unsubscribe should handle the appropriate algorithms for the publish/subscriber implementation.
239+
* For example, a Floodsub implementation might simply send a message for every peer revoking interest in the topics
240+
* @abstract
241+
* @param {Array<string>|string} topics
242+
* @returns {undefined}
243+
*/
244+
unsubscribe (topics) {
245+
throw errcode('unsubscribe must be implemented by the subclass', 'ERR_NOT_IMPLEMENTED')
246+
}
247+
162248
/**
163249
* Mounts the pubsub protocol onto the libp2p node and sends our
164250
* subscriptions to every peer conneceted

test/pubsub.js

+12
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ class PubsubImplementation extends PubsubBaseProtocol {
1717
super('libp2p:pubsub', 'libp2p:pubsub-implementation', libp2p)
1818
}
1919

20+
publish (topics, messages) {
21+
// ...
22+
}
23+
24+
subscribe (topics) {
25+
// ...
26+
}
27+
28+
unsubscribe (topics) {
29+
// ...
30+
}
31+
2032
_processConnection (idB58Str, conn, peer) {
2133
// ...
2234
}

0 commit comments

Comments
 (0)