@libp2p/peer-store 11.2.2-5b004c0c4 → 11.2.2-8e87be9e6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/store.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { NotFoundError } from '@libp2p/interface'
2
+ import { PeerMap, trackedPeerMap } from '@libp2p/peer-collections'
2
3
  import { peerIdFromCID } from '@libp2p/peer-id'
3
4
  import mortice from 'mortice'
4
5
  import { base32 } from 'multiformats/bases/base32'
@@ -13,7 +14,7 @@ import type { AddressFilter, PersistentPeerStoreComponents, PersistentPeerStoreI
13
14
  import type { PeerUpdate as PeerUpdateExternal, PeerId, Peer, PeerData, PeerQuery, Logger } from '@libp2p/interface'
14
15
  import type { AbortOptions } from '@multiformats/multiaddr'
15
16
  import type { Datastore, Key, Query } from 'interface-datastore'
16
- import type { Mortice } from 'mortice'
17
+ import type { Mortice, Release } from 'mortice'
17
18
 
18
19
  /**
19
20
  * Event detail emitted when peer data changes
@@ -53,10 +54,15 @@ function mapQuery (query: PeerQuery, maxAddressAge: number): Query {
53
54
  }
54
55
  }
55
56
 
57
+ export interface Lock {
58
+ refs: number
59
+ lock: Mortice
60
+ }
61
+
56
62
  export class PersistentStore {
57
63
  private readonly peerId: PeerId
58
64
  private readonly datastore: Datastore
59
- public readonly lock: Mortice
65
+ private locks: PeerMap<Lock>
60
66
  private readonly addressFilter?: AddressFilter
61
67
  private readonly log: Logger
62
68
  private readonly maxAddressAge: number
@@ -67,14 +73,77 @@ export class PersistentStore {
67
73
  this.peerId = components.peerId
68
74
  this.datastore = components.datastore
69
75
  this.addressFilter = init.addressFilter
70
- this.lock = mortice({
71
- name: 'peer-store',
72
- singleProcess: true
76
+ this.locks = trackedPeerMap({
77
+ name: 'libp2p_peer_store_locks',
78
+ metrics: components.metrics
73
79
  })
74
80
  this.maxAddressAge = init.maxAddressAge ?? MAX_ADDRESS_AGE
75
81
  this.maxPeerAge = init.maxPeerAge ?? MAX_PEER_AGE
76
82
  }
77
83
 
84
+ getLock (peerId: PeerId): Lock {
85
+ let lock = this.locks.get(peerId)
86
+
87
+ if (lock == null) {
88
+ lock = {
89
+ refs: 0,
90
+ lock: mortice({
91
+ name: peerId.toString(),
92
+ singleProcess: true
93
+ })
94
+ }
95
+
96
+ this.locks.set(peerId, lock)
97
+ }
98
+
99
+ lock.refs++
100
+
101
+ return lock
102
+ }
103
+
104
+ private maybeRemoveLock (peerId: PeerId, lock: Lock): void {
105
+ lock.refs--
106
+
107
+ if (lock.refs === 0) {
108
+ lock.lock.finalize()
109
+ this.locks.delete(peerId)
110
+ }
111
+ }
112
+
113
+ async getReadLock (peerId: PeerId, options?: AbortOptions): Promise<Release> {
114
+ const lock = this.getLock(peerId)
115
+
116
+ try {
117
+ const release = await lock.lock.readLock(options)
118
+
119
+ return () => {
120
+ release()
121
+ this.maybeRemoveLock(peerId, lock)
122
+ }
123
+ } catch (err) {
124
+ this.maybeRemoveLock(peerId, lock)
125
+
126
+ throw err
127
+ }
128
+ }
129
+
130
+ async getWriteLock (peerId: PeerId, options?: AbortOptions): Promise<Release> {
131
+ const lock = this.getLock(peerId)
132
+
133
+ try {
134
+ const release = await lock.lock.writeLock(options)
135
+
136
+ return () => {
137
+ release()
138
+ this.maybeRemoveLock(peerId, lock)
139
+ }
140
+ } catch (err) {
141
+ this.maybeRemoveLock(peerId, lock)
142
+
143
+ throw err
144
+ }
145
+ }
146
+
78
147
  async has (peerId: PeerId, options?: AbortOptions): Promise<boolean> {
79
148
  try {
80
149
  await this.load(peerId, options)
@@ -179,7 +248,7 @@ export class PersistentStore {
179
248
 
180
249
  return {
181
250
  peerPB,
182
- peer: bytesToPeer(peerId, buf, this.maxAddressAge)
251
+ peer: pbToPeer(peerId, peerPB, this.maxAddressAge)
183
252
  }
184
253
  } catch (err: any) {
185
254
  if (err.name !== 'NotFoundError') {
@@ -196,7 +265,7 @@ export class PersistentStore {
196
265
  await this.datastore.put(peerIdToDatastoreKey(peerId), buf, options)
197
266
 
198
267
  return {
199
- peer: bytesToPeer(peerId, buf, this.maxAddressAge),
268
+ peer: pbToPeer(peerId, peer, this.maxAddressAge),
200
269
  previous: existingPeer?.peer,
201
270
  updated: existingPeer == null || !peerEquals(peer, existingPeer.peerPB)
202
271
  }
@@ -1,22 +1,20 @@
1
1
  import { publicKeyFromProtobuf } from '@libp2p/crypto/keys'
2
2
  import { peerIdFromPublicKey } from '@libp2p/peer-id'
3
3
  import { multiaddr } from '@multiformats/multiaddr'
4
- import { base58btc } from 'multiformats/bases/base58'
5
- import * as Digest from 'multiformats/hashes/digest'
6
4
  import { Peer as PeerPB } from '../pb/peer.js'
7
5
  import type { PeerId, Peer, Tag } from '@libp2p/interface'
6
+ import type { Digest } from 'multiformats/hashes/digest'
8
7
 
9
8
  function populatePublicKey (peerId: PeerId, protobuf: PeerPB): PeerId {
10
9
  if (peerId.publicKey != null || protobuf.publicKey == null) {
11
10
  return peerId
12
11
  }
13
12
 
14
- let digest: any
13
+ let digest: Digest<18, number> | undefined
15
14
 
16
15
  if (peerId.type === 'RSA') {
17
16
  // avoid hashing public key
18
- const multihash = base58btc.decode(`z${peerId}`)
19
- digest = Digest.decode(multihash)
17
+ digest = peerId.toMultihash()
20
18
  }
21
19
 
22
20
  const publicKey = publicKeyFromProtobuf(protobuf.publicKey, digest)
@@ -252,8 +252,13 @@ function mapTag (key: string, tag: any): Tag {
252
252
  expiry = BigInt(Date.now() + Number(tag.ttl))
253
253
  }
254
254
 
255
- return {
256
- value: tag.value ?? 0,
257
- expiry
255
+ const output: Tag = {
256
+ value: tag.value ?? 0
258
257
  }
258
+
259
+ if (expiry != null) {
260
+ output.expiry = expiry
261
+ }
262
+
263
+ return output
259
264
  }