1
1
import { CodeError } from '@libp2p/interfaces/errors'
2
+ import { PeerMap } from '@libp2p/peer-collections'
2
3
import { peerIdFromBytes } from '@libp2p/peer-id'
3
4
import mortice , { type Mortice } from 'mortice'
4
5
import { base32 } from 'multiformats/bases/base32'
@@ -11,8 +12,8 @@ import { toPeerPB } from './utils/to-peer-pb.js'
11
12
import type { AddressFilter , PersistentPeerStoreComponents , PersistentPeerStoreInit } from './index.js'
12
13
import type { PeerUpdate as PeerUpdateExternal } from '@libp2p/interface-libp2p'
13
14
import type { PeerId } from '@libp2p/interface-peer-id'
14
- import type { Peer , PeerData } from '@libp2p/interface-peer-store'
15
- import type { Datastore } from 'interface-datastore'
15
+ import type { Peer , PeerData , PeerQuery } from '@libp2p/interface-peer-store'
16
+ import type { Datastore , Key , Query } from 'interface-datastore'
16
17
17
18
/**
18
19
* Event detail emitted when peer data changes
@@ -21,6 +22,41 @@ export interface PeerUpdate extends PeerUpdateExternal {
21
22
updated : boolean
22
23
}
23
24
25
+ function decodePeer ( key : Key , value : Uint8Array , cache : PeerMap < Peer > ) : Peer {
26
+ // /peers/${peer-id-as-libp2p-key-cid-string-in-base-32}
27
+ const base32Str = key . toString ( ) . split ( '/' ) [ 2 ]
28
+ const buf = base32 . decode ( base32Str )
29
+ const peerId = peerIdFromBytes ( buf )
30
+
31
+ const cached = cache . get ( peerId )
32
+
33
+ if ( cached != null ) {
34
+ return cached
35
+ }
36
+
37
+ const peer = bytesToPeer ( peerId , value )
38
+
39
+ cache . set ( peerId , peer )
40
+
41
+ return peer
42
+ }
43
+
44
+ function mapQuery ( query : PeerQuery , cache : PeerMap < Peer > ) : Query {
45
+ if ( query == null ) {
46
+ return { }
47
+ }
48
+
49
+ return {
50
+ prefix : NAMESPACE_COMMON ,
51
+ filters : ( query . filters ?? [ ] ) . map ( fn => ( { key, value } ) => {
52
+ return fn ( decodePeer ( key , value , cache ) )
53
+ } ) ,
54
+ orders : ( query . orders ?? [ ] ) . map ( fn => ( a , b ) => {
55
+ return fn ( decodePeer ( a . key , a . value , cache ) , decodePeer ( b . key , b . value , cache ) )
56
+ } )
57
+ }
58
+ }
59
+
24
60
export class PersistentStore {
25
61
private readonly peerId : PeerId
26
62
private readonly datastore : Datastore
@@ -96,28 +132,25 @@ export class PersistentStore {
96
132
return this . #saveIfDifferent( peerId , peerPb , existingBuf , existingPeer )
97
133
}
98
134
99
- async * all ( ) : AsyncGenerator < Peer , void , unknown > {
100
- for await ( const { key, value } of this . datastore . query ( {
101
- prefix : NAMESPACE_COMMON
102
- } ) ) {
103
- // /peers/${peer-id-as-libp2p-key-cid-string-in-base-32}
104
- const base32Str = key . toString ( ) . split ( '/' ) [ 2 ]
105
- const buf = base32 . decode ( base32Str )
106
- const peerId = peerIdFromBytes ( buf )
135
+ async * all ( query ?: PeerQuery ) : AsyncGenerator < Peer , void , unknown > {
136
+ const peerCache = new PeerMap < Peer > ( )
137
+
138
+ for await ( const { key, value } of this . datastore . query ( mapQuery ( query ?? { } , peerCache ) ) ) {
139
+ const peer = decodePeer ( key , value , peerCache )
107
140
108
- if ( peerId . equals ( this . peerId ) ) {
141
+ if ( peer . id . equals ( this . peerId ) ) {
109
142
// Skip self peer if present
110
143
continue
111
144
}
112
145
113
- yield bytesToPeer ( peerId , value )
146
+ yield peer
114
147
}
115
148
}
116
149
117
150
async #findExistingPeer ( peerId : PeerId ) : Promise < { existingBuf ?: Uint8Array , existingPeer ?: Peer } > {
118
151
try {
119
152
const existingBuf = await this . datastore . get ( peerIdToDatastoreKey ( peerId ) )
120
- const existingPeer = await bytesToPeer ( peerId , existingBuf )
153
+ const existingPeer = bytesToPeer ( peerId , existingBuf )
121
154
122
155
return {
123
156
existingBuf,
@@ -137,7 +170,7 @@ export class PersistentStore {
137
170
138
171
if ( existingBuf != null && uint8ArrayEquals ( buf , existingBuf ) ) {
139
172
return {
140
- peer : await bytesToPeer ( peerId , buf ) ,
173
+ peer : bytesToPeer ( peerId , buf ) ,
141
174
previous : existingPeer ,
142
175
updated : false
143
176
}
@@ -146,7 +179,7 @@ export class PersistentStore {
146
179
await this . datastore . put ( peerIdToDatastoreKey ( peerId ) , buf )
147
180
148
181
return {
149
- peer : await bytesToPeer ( peerId , buf ) ,
182
+ peer : bytesToPeer ( peerId , buf ) ,
150
183
previous : existingPeer ,
151
184
updated : true
152
185
}
0 commit comments