Skip to content

Commit 17eb162

Browse files
authored
feat: add event bus (#1693)
Adds an event emitter as a libp2p component that will echo every emitted event on the main libp2p object. Closes #1574 Fixes #1630
1 parent 8d408d5 commit 17eb162

File tree

85 files changed

+1267
-999
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1267
-999
lines changed

doc/GETTING_STARTED.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ node.addEventListener('peer:discovery', (evt) => {
216216
console.log('Discovered %s', evt.detail.id.toString()) // Log discovered peer
217217
})
218218

219-
node.connectionManager.addEventListener('peer:connect', (evt) => {
219+
node.addEventListener('peer:connect', (evt) => {
220220
console.log('Connected to %s', evt.detail.remotePeer.toString()) // Log connected peer
221221
})
222222
```

doc/migrations/v0.44-v0.45.md

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Migrating to libp2p@45 <!-- omit in toc -->
2+
3+
A migration guide for refactoring your application code from libp2p v0.44.x to v0.45.0.
4+
5+
## Table of Contents <!-- omit in toc -->
6+
7+
- [Events](#events)
8+
- [Emitters](#emitters)
9+
- [Event changes](#event-changes)
10+
- [`peer:connect`](#peerconnect)
11+
- [`peer:disconnect`](#peerdisconnect)
12+
- [`peer:update`](#peerupdate)
13+
- [`self:peer:update`](#selfpeerupdate)
14+
- [Atomic peer store methods](#atomic-peer-store-methods)
15+
16+
## Events
17+
18+
The events emitted by libp2p have been refactored to be more consistent and to give more insight into the inner workings of libp2p.
19+
20+
> Please see the [API docs](https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_libp2p.Libp2pEvents.html) for an exhaustive list of events emitted by Libp2p.
21+
22+
### Emitters
23+
24+
The primary interaction point for events is now the libp2p node itself, no need to access internal properties to set up listeners.
25+
26+
**Before**
27+
28+
```js
29+
import { createLibp2p } from 'libp2p'
30+
31+
const node = await createLibp2p({ /* ... */ })
32+
node.connectionManager.addEventListener('peer:connect', () => {})
33+
```
34+
35+
**After**
36+
37+
```js
38+
import { createLibp2p } from 'libp2p'
39+
40+
const node = await createLibp2p({ /* ... */ })
41+
node.addEventListener('peer:connect', () => {})
42+
```
43+
44+
### Event changes
45+
46+
Some types have changed.
47+
48+
> Please see the [API docs](https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_libp2p.Libp2pEvents.html) for an exhaustive list of events emitted by Libp2p.
49+
50+
#### `peer:connect`
51+
52+
The detail field for this event was a [Connection] now it is a [PeerId]
53+
54+
It is emitted when a new peer opens it's first connection.
55+
56+
To receive notifications of the opening of individual connections, listen for the `connection:open` event instead.
57+
58+
#### `peer:disconnect`
59+
60+
The detail field for this event was a [Connection] now it is a [PeerId]
61+
62+
It is emitted when all connections for the peer have been closed.
63+
64+
To receive notifications of the closing of individual connections, listen for the `connection:close` event instead.
65+
66+
#### `peer:update`
67+
68+
This event is emitted when a peer's data has been changed in the peer store. This can be in response to a user manually updating the peer, or after the [Identify] protocol has completed.
69+
70+
#### `self:peer:update`
71+
72+
This event occurs when the data of the running node has changed. It may have started listening on a new multiaddr, [AutoNAT] may have given us new confidence in an external address or a user may have manually updated the information.
73+
74+
## Atomic peer store methods
75+
76+
The libp2p peer store has been refactored to reduce the number of methods it exposes.
77+
78+
Previously it had separate components for managing addresses, protocols, metadata, etc, all of which exposed async methods which meant updating the data for a peer could involve multiple async calls which required complicated internal locking mechanisms which introduced a lot of latency into libp2p nodes performing many peer operations.
79+
80+
The updated peer store has simple `save`, `patch` and `merge` methods which update all fields in a peer's stored data at once.
81+
82+
**Before**
83+
84+
```js
85+
import { createLibp2p } from 'libp2p'
86+
87+
const node = await createLibp2p({ /* ... */ })
88+
89+
// add addresses
90+
await node.peerStore.addressBook.add(peerId, [
91+
multiaddr('/ip4/43.14.67.21/tcp/3847')
92+
])
93+
94+
// set protocols
95+
await node.peerStore.protoBook.set(peerId, [
96+
'/a-proto/1.0.0',
97+
'/another-proto/1.0.0'
98+
])
99+
100+
// add metadata
101+
await node.peerStore.metadataBook.set(peerId, 'key', Uint8Array.from([0, 1, 2, 3]))
102+
103+
// add tags
104+
await node.peerStore.tagPeer(peerId, 'tag-name', { value: 10 })
105+
```
106+
107+
**After**
108+
109+
```js
110+
import { createLibp2p } from 'libp2p'
111+
112+
const node = await createLibp2p({ /* ... */ })
113+
114+
// `save` replaces all data for the peer. Use with caution - any fields not passed
115+
// will be deleted
116+
await node.peerStore.save(peerId, {
117+
multiaddrs: [
118+
multiaddr('/ip4/43.14.67.21/tcp/3847')
119+
],
120+
protocols: [
121+
'/a-proto/1.0.0',
122+
'/another-proto/1.0.0'
123+
],
124+
metadata: {
125+
key: Uint8Array.from([0, 1, 2, 3])
126+
},
127+
tags: {
128+
'tag-name': { value: 10 }
129+
}
130+
})
131+
```
132+
133+
Other ways to update peers are available which are more concise and allow you to just update specific fields:
134+
135+
```js
136+
// `patch` replaces only the passed fields and retains all other data
137+
await node.peerStore.patch(peerId, {
138+
multiaddrs: [
139+
multiaddr('/ip4/43.14.67.21/tcp/3847')
140+
]
141+
})
142+
143+
// `merge` behaves like `patch` but deeply merges multiaddrs, protocols, metadata,
144+
// and tags, removing duplicates. any existing metadata/tags with the same
145+
// keys/tag names will be overwritten.
146+
await node.peerStore.merge(peerId, {
147+
multiaddrs: [
148+
multiaddr('/ip4/43.14.67.21/tcp/3847')
149+
]
150+
})
151+
```
152+
153+
You can also remove fields quickly:
154+
155+
```js
156+
// passing `undefined` to `merge` is a quick way of deleting metadata/tags
157+
await node.peerStore.merge(peerId, {
158+
metadata: {
159+
key: undefined
160+
},
161+
tags: {
162+
'tag-name': undefined
163+
}
164+
})
165+
```
166+
167+
[Connection]: https://libp2p.github.io/js-libp2p-interfaces/interfaces/_libp2p_interface_connection.Connection.html
168+
[PeerId]: https://libp2p.github.io/js-libp2p-interfaces/types/_libp2p_interface_peer_id.PeerId.html
169+
[Identify]: https://github.com/libp2p/specs/blob/master/identify/README.md
170+
[AutoNAT]: https://github.com/libp2p/specs/blob/master/autonat/README.md

examples/auto-relay/README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,9 @@ const conn = await node.dial(relayAddr)
9898
console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`)
9999

100100
// Wait for connection and relay to be bind for the example purpose
101-
node.peerStore.addEventListener('change:multiaddrs', (evt) => {
101+
node.addEventListener('self:peer:update', (evt) => {
102102
// Updated self multiaddrs?
103-
if (evt.detail.peerId.equals(node.peerId)) {
104-
console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`)
105-
}
103+
console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`)
106104
})
107105
```
108106

examples/auto-relay/listener.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,9 @@ async function main () {
3333
console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`)
3434

3535
// Wait for connection and relay to be bind for the example purpose
36-
node.peerStore.addEventListener('change:multiaddrs', (evt) => {
37-
const { peerId } = evt.detail
38-
36+
node.addEventListener('self:peer:update', (evt) => {
3937
// Updated self multiaddrs?
40-
if (peerId.equals(node.peerId)) {
41-
console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`)
42-
}
38+
console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`)
4339
})
4440
}
4541

examples/chat/src/listener.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async function run () {
1616
})
1717

1818
// Log a message when a remote peer connects to us
19-
nodeListener.connectionManager.addEventListener('peer:connect', (evt) => {
19+
nodeListener.addEventListener('peer:connect', (evt) => {
2020
const connection = evt.detail
2121
console.log('connected to: ', connection.remotePeer.toString())
2222
})

examples/connection-encryption/1.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ const createNode = async () => {
2525
createNode()
2626
])
2727

28-
await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs())
28+
await node1.peerStore.patch(node2.peerId, {
29+
multiaddrs: node2.getMultiaddrs()
30+
})
2931

3032
node2.handle('/a-protocol', ({ stream }) => {
3133
pipe(

examples/delegated-routing/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
"libp2p": "file:../../",
1010
"@libp2p/delegated-content-routing": "^4.0.0",
1111
"@libp2p/delegated-peer-routing": "^4.0.0",
12-
"@libp2p/kad-dht": "^8.0.7",
13-
"@libp2p/mplex": "^7.1.6",
14-
"@libp2p/webrtc-star": "^6.0.0",
15-
"@libp2p/websockets": "^5.0.0",
12+
"@libp2p/kad-dht": "^9.0.0",
13+
"@libp2p/mplex": "^8.0.1",
14+
"@libp2p/webrtc-star": "^7.0.0",
15+
"@libp2p/websockets": "^6.0.1",
1616
"react": "^17.0.2",
1717
"react-dom": "^17.0.2",
1818
"react-scripts": "5.0.0"

examples/discovery-mechanisms/1.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ import bootstrappers from './bootstrappers.js'
2222
]
2323
})
2424

25-
node.connectionManager.addEventListener('peer:connect', (evt) => {
26-
const connection = evt.detail
27-
console.log('Connection established to:', connection.remotePeer.toString()) // Emitted when a peer has been found
25+
node.addEventListener('peer:connect', (evt) => {
26+
const peerId = evt.detail
27+
console.log('Connection established to:', peerId.toString()) // Emitted when a peer has been found
2828
})
2929

3030
node.addEventListener('peer:discovery', (evt) => {
31-
const peer = evt.detail
31+
const peerId = evt.detail
3232

33-
console.log('Discovered:', peer.id.toString())
33+
console.log('Discovered:', peerId.toString())
3434
})
3535
})();

examples/discovery-mechanisms/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const node = await createLibp2p({
7676
]
7777
})
7878

79-
node.connectionManager.addEventListener('peer:connect', (evt) => {
79+
node.addEventListener('peer:connect', (evt) => {
8080
console.log('Connection established to:', evt.detail.remotePeer.toString()) // Emitted when a new connection has been created
8181
})
8282

examples/echo/src/listener.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ async function run() {
2121
})
2222

2323
// Log a message when we receive a connection
24-
listenerNode.connectionManager.addEventListener('peer:connect', (evt) => {
24+
listenerNode.addEventListener('peer:connect', (evt) => {
2525
const connection = evt.detail
2626
console.log('received dial to me from:', connection.remotePeer.toString())
2727
})

examples/libp2p-in-the-browser/index.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,25 @@ document.addEventListener('DOMContentLoaded', async () => {
5252

5353
// Listen for new peers
5454
libp2p.addEventListener('peer:discovery', (evt) => {
55-
const peer = evt.detail
56-
log(`Found peer ${peer.id.toString()}`)
55+
const peerInfo = evt.detail
56+
log(`Found peer ${peerInfo.id.toString()}`)
5757

5858
// dial them when we discover them
59-
libp2p.dial(evt.detail.id).catch(err => {
60-
log(`Could not dial ${evt.detail.id}`, err)
59+
libp2p.dial(peerInfo.id).catch(err => {
60+
log(`Could not dial ${peerInfo.id.toString()}`, err)
6161
})
6262
})
6363

6464
// Listen for new connections to peers
65-
libp2p.connectionManager.addEventListener('peer:connect', (evt) => {
66-
const connection = evt.detail
67-
log(`Connected to ${connection.remotePeer.toString()}`)
65+
libp2p.addEventListener('peer:connect', (evt) => {
66+
const peerId = evt.detail
67+
log(`Connected to ${peerId.toString()}`)
6868
})
6969

7070
// Listen for peers disconnecting
71-
libp2p.connectionManager.addEventListener('peer:disconnect', (evt) => {
72-
const connection = evt.detail
73-
log(`Disconnected from ${connection.remotePeer.toString()}`)
71+
libp2p.addEventListener('peer:disconnect', (evt) => {
72+
const peerId = evt.detail
73+
log(`Disconnected from ${peerId.toString()}`)
7474
})
7575

7676
status.innerText = 'libp2p started!'

examples/libp2p-in-the-browser/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
"license": "ISC",
1111
"dependencies": {
1212
"@chainsafe/libp2p-noise": "^11.0.0",
13-
"@libp2p/bootstrap": "^6.0.0",
14-
"@libp2p/mplex": "^7.1.6",
15-
"@libp2p/webrtc-star": "^6.0.0",
16-
"@libp2p/websockets": "^5.0.0",
13+
"@libp2p/bootstrap": "^7.0.0",
14+
"@libp2p/mplex": "^8.0.1",
15+
"@libp2p/webrtc-star": "^7.0.0",
16+
"@libp2p/websockets": "^6.0.1",
1717
"libp2p": "file:../../"
1818
},
1919
"devDependencies": {

examples/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"license": "MIT",
1111
"dependencies": {
12-
"@libp2p/floodsub": "^6.0.0",
12+
"@libp2p/floodsub": "^7.0.1",
1313
"@libp2p/pubsub-peer-discovery": "^8.0.0",
1414
"@nodeutils/defaults-deep": "^1.1.0",
1515
"execa": "^6.1.0",

examples/peer-and-content-routing/1.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ const createNode = async () => {
2828
createNode()
2929
])
3030

31-
await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs())
32-
await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs())
31+
await node1.peerStore.patch(node2.peerId, {
32+
multiaddrs: node2.getMultiaddrs()
33+
})
34+
await node2.peerStore.patch(node3.peerId, {
35+
multiaddrs: node3.getMultiaddrs()
36+
})
3337

3438
await Promise.all([
3539
node1.dial(node2.peerId),

examples/peer-and-content-routing/2.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@ const createNode = async () => {
3030
createNode()
3131
])
3232

33-
await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs())
34-
await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs())
33+
await node1.peerStore.patch(node2.peerId, {
34+
multiaddrs: node2.getMultiaddrs()
35+
})
36+
await node2.peerStore.patch(node3.peerId, {
37+
multiaddrs: node3.getMultiaddrs()
38+
})
3539

3640
await Promise.all([
3741
node1.dial(node2.peerId),

examples/peer-and-content-routing/README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ const [node1, node2, node3] = await Promise.all([
4343
createNode()
4444
])
4545

46-
await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs())
47-
await node2.peerStore.addressBook.set(node3.peerId, node3.getMultiaddrs())
46+
await node1.peerStore.patch(node2.peerId, {
47+
multiaddrs: node2.getMultiaddrs()
48+
})
49+
await node2.peerStore.patch(node3.peerId, {
50+
mulitaddrs: node3.getMultiaddrs()
51+
})
4852

4953
await Promise.all([
5054
node1.dial(node2.peerId),

examples/pnet/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ generateKey(otherSwarmKey)
2424
console.log('nodes started...')
2525

2626
// Add node 2 data to node1's PeerStore
27-
await node1.peerStore.addressBook.set(node2.peerId, node2.getMultiaddrs())
27+
await node1.peerStore.patch(node2.peerId, {
28+
multiaddrs: node2.getMultiaddrs()
29+
})
2830
await node1.dial(node2.peerId)
2931

3032
node2.handle('/private', ({ stream }) => {

0 commit comments

Comments
 (0)