@libp2p/kad-dht 14.0.2 → 14.1.0-02f285fc8

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.
Files changed (83) hide show
  1. package/README.md +36 -0
  2. package/dist/index.min.js +2 -2
  3. package/dist/src/constants.d.ts +4 -3
  4. package/dist/src/constants.d.ts.map +1 -1
  5. package/dist/src/constants.js +8 -3
  6. package/dist/src/constants.js.map +1 -1
  7. package/dist/src/content-fetching/index.d.ts +1 -0
  8. package/dist/src/content-fetching/index.d.ts.map +1 -1
  9. package/dist/src/content-fetching/index.js +5 -3
  10. package/dist/src/content-fetching/index.js.map +1 -1
  11. package/dist/src/index.d.ts +107 -2
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/index.js +36 -0
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/kad-dht.d.ts +14 -1
  16. package/dist/src/kad-dht.d.ts.map +1 -1
  17. package/dist/src/kad-dht.js +76 -27
  18. package/dist/src/kad-dht.js.map +1 -1
  19. package/dist/src/network.d.ts +1 -0
  20. package/dist/src/network.d.ts.map +1 -1
  21. package/dist/src/network.js +4 -5
  22. package/dist/src/network.js.map +1 -1
  23. package/dist/src/peer-routing/index.d.ts.map +1 -1
  24. package/dist/src/peer-routing/index.js +9 -10
  25. package/dist/src/peer-routing/index.js.map +1 -1
  26. package/dist/src/providers.d.ts +21 -50
  27. package/dist/src/providers.d.ts.map +1 -1
  28. package/dist/src/providers.js +51 -192
  29. package/dist/src/providers.js.map +1 -1
  30. package/dist/src/query/manager.d.ts +1 -1
  31. package/dist/src/query/manager.d.ts.map +1 -1
  32. package/dist/src/query/manager.js +8 -19
  33. package/dist/src/query/manager.js.map +1 -1
  34. package/dist/src/query-self.d.ts +3 -1
  35. package/dist/src/query-self.d.ts.map +1 -1
  36. package/dist/src/query-self.js +17 -16
  37. package/dist/src/query-self.js.map +1 -1
  38. package/dist/src/reprovider.d.ts +63 -0
  39. package/dist/src/reprovider.d.ts.map +1 -0
  40. package/dist/src/reprovider.js +161 -0
  41. package/dist/src/reprovider.js.map +1 -0
  42. package/dist/src/routing-table/closest-peers.d.ts +1 -0
  43. package/dist/src/routing-table/closest-peers.d.ts.map +1 -1
  44. package/dist/src/routing-table/closest-peers.js +7 -0
  45. package/dist/src/routing-table/closest-peers.js.map +1 -1
  46. package/dist/src/routing-table/index.d.ts +1 -0
  47. package/dist/src/routing-table/index.d.ts.map +1 -1
  48. package/dist/src/routing-table/index.js +14 -11
  49. package/dist/src/routing-table/index.js.map +1 -1
  50. package/dist/src/rpc/handlers/get-value.d.ts +1 -0
  51. package/dist/src/rpc/handlers/get-value.d.ts.map +1 -1
  52. package/dist/src/rpc/handlers/get-value.js +3 -1
  53. package/dist/src/rpc/handlers/get-value.js.map +1 -1
  54. package/dist/src/rpc/handlers/put-value.d.ts +1 -0
  55. package/dist/src/rpc/handlers/put-value.d.ts.map +1 -1
  56. package/dist/src/rpc/handlers/put-value.js +3 -1
  57. package/dist/src/rpc/handlers/put-value.js.map +1 -1
  58. package/dist/src/rpc/index.d.ts +1 -0
  59. package/dist/src/rpc/index.d.ts.map +1 -1
  60. package/dist/src/rpc/index.js +9 -10
  61. package/dist/src/rpc/index.js.map +1 -1
  62. package/dist/src/utils.d.ts +20 -1
  63. package/dist/src/utils.d.ts.map +1 -1
  64. package/dist/src/utils.js +87 -4
  65. package/dist/src/utils.js.map +1 -1
  66. package/package.json +12 -14
  67. package/src/constants.ts +11 -5
  68. package/src/content-fetching/index.ts +5 -3
  69. package/src/index.ts +116 -2
  70. package/src/kad-dht.ts +94 -41
  71. package/src/network.ts +5 -5
  72. package/src/peer-routing/index.ts +9 -11
  73. package/src/providers.ts +57 -244
  74. package/src/query/manager.ts +12 -28
  75. package/src/query-self.ts +20 -17
  76. package/src/reprovider.ts +226 -0
  77. package/src/routing-table/closest-peers.ts +9 -0
  78. package/src/routing-table/index.ts +16 -11
  79. package/src/rpc/handlers/get-value.ts +3 -1
  80. package/src/rpc/handlers/put-value.ts +3 -1
  81. package/src/rpc/index.ts +10 -10
  82. package/src/utils.ts +102 -4
  83. package/dist/typedoc-urls.json +0 -56
package/src/providers.ts CHANGED
@@ -1,292 +1,105 @@
1
- import { peerIdFromString } from '@libp2p/peer-id'
2
- import cache from 'hashlru'
3
- import { Key } from 'interface-datastore/key'
4
- import Queue from 'p-queue'
1
+ import { PeerMap } from '@libp2p/peer-collections'
5
2
  import * as varint from 'uint8-varint'
6
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
7
- import {
8
- PROVIDERS_CLEANUP_INTERVAL,
9
- PROVIDERS_VALIDITY,
10
- PROVIDERS_LRU_CACHE_SIZE,
11
- PROVIDER_KEY_PREFIX
12
- } from './constants.js'
13
- import type { ComponentLogger, Logger, PeerId, Startable } from '@libp2p/interface'
3
+ import { parseProviderKey, readProviderTime, toProviderKey } from './utils.js'
4
+ import type { ComponentLogger, Logger, Metrics, PeerId } from '@libp2p/interface'
14
5
  import type { Datastore } from 'interface-datastore'
6
+ import type { Mortice } from 'mortice'
15
7
  import type { CID } from 'multiformats'
16
8
 
17
9
  export interface ProvidersInit {
18
- /**
19
- * @default 256
20
- */
21
- cacheSize?: number
22
- /**
23
- * How often invalid records are cleaned. (in seconds)
24
- *
25
- * @default 5400
26
- */
27
- cleanupInterval?: number
28
- /**
29
- * How long is a provider valid for. (in seconds)
30
- *
31
- * @default 86400
32
- */
33
- provideValidity?: number
10
+ logPrefix: string
11
+ datastorePrefix: string
12
+ lock: Mortice
34
13
  }
35
14
 
36
15
  export interface ProvidersComponents {
37
16
  datastore: Datastore
38
17
  logger: ComponentLogger
18
+ metrics?: Metrics
39
19
  }
40
20
 
41
21
  /**
42
- * This class manages known providers.
43
- * A provider is a peer that we know to have the content for a given CID.
44
- *
45
- * Every `cleanupInterval` providers are checked if they
46
- * are still valid, i.e. younger than the `provideValidity`.
47
- * If they are not, they are deleted.
48
- *
49
- * To ensure the list survives restarts of the daemon,
50
- * providers are stored in the datastore, but to ensure
51
- * access is fast there is an LRU cache in front of that.
22
+ * Provides a mechanism to add and remove provider records from the datastore
52
23
  */
53
- export class Providers implements Startable {
24
+ export class Providers {
54
25
  private readonly log: Logger
55
26
  private readonly datastore: Datastore
56
- private readonly cache: ReturnType<typeof cache>
57
- private readonly cleanupInterval: number
58
- private readonly provideValidity: number
59
- private readonly syncQueue: Queue
60
- private started: boolean
61
- private cleaner?: ReturnType<typeof setInterval>
62
-
63
- constructor (components: ProvidersComponents, init: ProvidersInit = {}) {
64
- const { cacheSize, cleanupInterval, provideValidity } = init
27
+ private readonly datastorePrefix: string
28
+ private readonly lock: Mortice
65
29
 
66
- this.log = components.logger.forComponent('libp2p:kad-dht:providers')
30
+ constructor (components: ProvidersComponents, init: ProvidersInit) {
31
+ this.log = components.logger.forComponent(`${init.logPrefix}:providers`)
32
+ this.datastorePrefix = `/${init.datastorePrefix}/provider`
67
33
  this.datastore = components.datastore
68
- this.cleanupInterval = cleanupInterval ?? PROVIDERS_CLEANUP_INTERVAL
69
- this.provideValidity = provideValidity ?? PROVIDERS_VALIDITY
70
- this.cache = cache(cacheSize ?? PROVIDERS_LRU_CACHE_SIZE)
71
- this.syncQueue = new Queue({ concurrency: 1 })
72
- this.started = false
73
- }
74
-
75
- isStarted (): boolean {
76
- return this.started
34
+ this.lock = init.lock
77
35
  }
78
36
 
79
37
  /**
80
- * Start the provider cleanup service
38
+ * Add a new provider for the given CID
81
39
  */
82
- async start (): Promise<void> {
83
- if (this.started) {
84
- return
85
- }
86
-
87
- this.started = true
40
+ async addProvider (cid: CID, provider: PeerId): Promise<void> {
41
+ const release = await this.lock.readLock()
88
42
 
89
- this.cleaner = setInterval(
90
- () => {
91
- this._cleanup().catch(err => {
92
- this.log.error(err)
93
- })
94
- },
95
- this.cleanupInterval
96
- )
43
+ try {
44
+ this.log('%p provides %s', provider, cid)
45
+ await this.writeProviderEntry(cid, provider)
46
+ } finally {
47
+ release()
48
+ }
97
49
  }
98
50
 
99
51
  /**
100
- * Release any resources.
52
+ * Remove a provider for the given CID
101
53
  */
102
- async stop (): Promise<void> {
103
- this.started = false
104
-
105
- if (this.cleaner != null) {
106
- clearInterval(this.cleaner)
107
- this.cleaner = undefined
54
+ async removeProvider (cid: CID, provider: PeerId): Promise<void> {
55
+ const release = await this.lock.writeLock()
56
+
57
+ try {
58
+ const key = toProviderKey(this.datastorePrefix, cid, provider)
59
+ this.log('%p no longer provides %s', provider, cid)
60
+ await this.datastore.delete(key)
61
+ } finally {
62
+ release()
108
63
  }
109
64
  }
110
65
 
111
66
  /**
112
- * Check all providers if they are still valid, and if not delete them
67
+ * Get a list of providers for the given CID
113
68
  */
114
- async _cleanup (): Promise<void> {
115
- await this.syncQueue.add(async () => {
116
- const start = Date.now()
117
-
118
- let count = 0
119
- let deleteCount = 0
120
- const deleted = new Map<string, Set<string>>()
121
- const batch = this.datastore.batch()
122
-
123
- // Get all provider entries from the datastore
124
- const query = this.datastore.query({ prefix: PROVIDER_KEY_PREFIX })
125
-
126
- for await (const entry of query) {
127
- try {
128
- // Add a delete to the batch for each expired entry
129
- const { cid, peerId } = parseProviderKey(entry.key)
130
- const time = readTime(entry.value).getTime()
131
- const now = Date.now()
132
- const delta = now - time
133
- const expired = delta > this.provideValidity
134
-
135
- this.log('comparing: %d - %d = %d > %d %s', now, time, delta, this.provideValidity, expired ? '(expired)' : '')
136
-
137
- if (expired) {
138
- deleteCount++
139
- batch.delete(entry.key)
140
- const peers = deleted.get(cid) ?? new Set<string>()
141
- peers.add(peerId)
142
- deleted.set(cid, peers)
143
- }
144
- count++
145
- } catch (err: any) {
146
- this.log.error(err.message)
147
- }
148
- }
149
-
150
- // Commit the deletes to the datastore
151
- if (deleted.size > 0) {
152
- this.log('deleting %d / %d entries', deleteCount, count)
153
- await batch.commit()
154
- } else {
155
- this.log('nothing to delete')
156
- }
157
-
158
- // Clear expired entries from the cache
159
- for (const [cid, peers] of deleted) {
160
- const key = makeProviderKey(cid)
161
- const provs = this.cache.get(key)
162
-
163
- if (provs != null) {
164
- for (const peerId of peers) {
165
- provs.delete(peerId)
166
- }
167
-
168
- if (provs.size === 0) {
169
- this.cache.remove(key)
170
- } else {
171
- this.cache.set(key, provs)
172
- }
173
- }
174
- }
175
-
176
- this.log('Cleanup successful (%dms)', Date.now() - start)
177
- })
178
- }
69
+ async getProviders (cid: CID): Promise<PeerId[]> {
70
+ const release = await this.lock.readLock()
179
71
 
180
- /**
181
- * Get the currently known provider peer ids for a given CID
182
- */
183
- async _getProvidersMap (cid: CID): Promise<Map<string, Date>> {
184
- const cacheKey = makeProviderKey(cid)
185
- let provs: Map<string, Date> = this.cache.get(cacheKey)
72
+ try {
73
+ this.log('get providers for %s', cid)
74
+ const provs = await this.loadProviders(cid)
186
75
 
187
- if (provs == null) {
188
- provs = await loadProviders(this.datastore, cid)
189
- this.cache.set(cacheKey, provs)
76
+ return [...provs.keys()]
77
+ } finally {
78
+ release()
190
79
  }
191
-
192
- return provs
193
80
  }
194
81
 
195
82
  /**
196
- * Add a new provider for the given CID
83
+ * Write a provider into the given store
197
84
  */
198
- async addProvider (cid: CID, provider: PeerId): Promise<void> {
199
- await this.syncQueue.add(async () => {
200
- this.log('%p provides %s', provider, cid)
201
- const provs = await this._getProvidersMap(cid)
202
-
203
- this.log('loaded %s provs', provs.size)
204
- const now = new Date()
205
- provs.set(provider.toString(), now)
206
-
207
- const dsKey = makeProviderKey(cid)
208
- this.cache.set(dsKey, provs)
85
+ private async writeProviderEntry (cid: CID, peerId: PeerId, time: Date = new Date()): Promise<void> {
86
+ const key = toProviderKey(this.datastorePrefix, cid, peerId)
87
+ const buffer = varint.encode(time.getTime())
209
88
 
210
- await writeProviderEntry(this.datastore, cid, provider, now)
211
- })
89
+ await this.datastore.put(key, buffer)
212
90
  }
213
91
 
214
92
  /**
215
- * Get a list of providers for the given CID
93
+ * Load providers for the given CID from the store
216
94
  */
217
- async getProviders (cid: CID): Promise<PeerId[]> {
218
- return this.syncQueue.add(async () => {
219
- this.log('get providers for %s', cid)
220
- const provs = await this._getProvidersMap(cid)
221
-
222
- return [...provs.keys()].map(peerIdStr => {
223
- return peerIdFromString(peerIdStr)
224
- })
225
- }, {
226
- // no timeout is specified for this queue so it will not
227
- // throw, but this is required to get the right return
228
- // type since p-queue@7.3.4
229
- throwOnTimeout: true
230
- })
231
- }
232
- }
233
-
234
- /**
235
- * Encode the given key its matching datastore key
236
- */
237
- function makeProviderKey (cid: CID | string): string {
238
- const cidStr = typeof cid === 'string' ? cid : uint8ArrayToString(cid.multihash.bytes, 'base32')
239
-
240
- return `${PROVIDER_KEY_PREFIX}/${cidStr}`
241
- }
242
-
243
- /**
244
- * Write a provider into the given store
245
- */
246
- async function writeProviderEntry (store: Datastore, cid: CID, peer: PeerId, time: Date): Promise<void> {
247
- const dsKey = [
248
- makeProviderKey(cid),
249
- '/',
250
- peer.toString()
251
- ].join('')
95
+ private async loadProviders (cid: CID): Promise<PeerMap<Date>> {
96
+ const providers = new PeerMap<Date>()
252
97
 
253
- const key = new Key(dsKey)
254
- const buffer = varint.encode(time.getTime())
255
-
256
- await store.put(key, buffer)
257
- }
258
-
259
- /**
260
- * Parse the CID and provider peer id from the key
261
- */
262
- function parseProviderKey (key: Key): { cid: string, peerId: string } {
263
- const parts = key.toString().split('/')
264
-
265
- if (parts.length !== 5) {
266
- throw new Error(`incorrectly formatted provider entry key in datastore: ${key.toString()}`)
267
- }
268
-
269
- return {
270
- cid: parts[3],
271
- peerId: parts[4]
272
- }
273
- }
274
-
275
- /**
276
- * Load providers for the given CID from the store
277
- */
278
- async function loadProviders (store: Datastore, cid: CID): Promise<Map<string, Date>> {
279
- const providers = new Map<string, Date>()
280
- const query = store.query({ prefix: makeProviderKey(cid) })
98
+ for await (const entry of this.datastore.query({ prefix: toProviderKey(this.datastorePrefix, cid).toString() })) {
99
+ const { peerId } = parseProviderKey(entry.key)
100
+ providers.set(peerId, readProviderTime(entry.value))
101
+ }
281
102
 
282
- for await (const entry of query) {
283
- const { peerId } = parseProviderKey(entry.key)
284
- providers.set(peerId, readTime(entry.value))
103
+ return providers
285
104
  }
286
-
287
- return providers
288
- }
289
-
290
- function readTime (buf: Uint8Array): Date {
291
- return new Date(varint.decode(buf))
292
105
  }
@@ -12,7 +12,7 @@ import { queryPath } from './query-path.js'
12
12
  import type { QueryFunc } from './types.js'
13
13
  import type { QueryEvent } from '../index.js'
14
14
  import type { RoutingTable } from '../routing-table/index.js'
15
- import type { ComponentLogger, Counter, Metric, Metrics, PeerId, RoutingOptions, Startable } from '@libp2p/interface'
15
+ import type { ComponentLogger, Metrics, PeerId, RoutingOptions, Startable } from '@libp2p/interface'
16
16
  import type { ConnectionManager } from '@libp2p/interface-internal'
17
17
  import type { DeferredPromise } from 'p-defer'
18
18
 
@@ -22,6 +22,7 @@ export interface CleanUpEvents {
22
22
 
23
23
  export interface QueryManagerInit {
24
24
  logPrefix: string
25
+ metricsPrefix: string
25
26
  disjointPaths?: number
26
27
  alpha?: number
27
28
  initialQuerySelfHasRun: DeferredPromise<void>
@@ -58,35 +59,23 @@ export class QueryManager implements Startable {
58
59
  private readonly routingTable: RoutingTable
59
60
  private initialQuerySelfHasRun?: DeferredPromise<void>
60
61
  private readonly logPrefix: string
61
- private readonly metrics: {
62
- queries?: Counter
63
- errors?: Counter
64
- queryTime?: Metric
65
- }
66
62
 
67
63
  constructor (components: QueryManagerComponents, init: QueryManagerInit) {
68
- const { disjointPaths = K, alpha = ALPHA, logPrefix } = init
69
-
70
- this.logPrefix = logPrefix
71
- this.disjointPaths = disjointPaths ?? K
72
- this.running = false
73
- this.alpha = alpha ?? ALPHA
64
+ this.logPrefix = init.logPrefix
65
+ this.disjointPaths = init.disjointPaths ?? K
66
+ this.alpha = init.alpha ?? ALPHA
74
67
  this.initialQuerySelfHasRun = init.initialQuerySelfHasRun
75
68
  this.routingTable = init.routingTable
76
69
  this.logger = components.logger
77
70
  this.peerId = components.peerId
78
71
  this.connectionManager = components.connectionManager
79
72
 
80
- this.metrics = {
81
- queries: components.metrics?.registerCounter(`${logPrefix.replaceAll(':', '_')}_queries_total`),
82
- errors: components.metrics?.registerCounter(`${logPrefix.replaceAll(':', '_')}_query_errors_total`),
83
- queryTime: components.metrics?.registerMetric(`${logPrefix.replaceAll(':', '_')}_query_time_seconds`)
84
- }
85
-
86
73
  // allow us to stop queries on shut down
87
74
  this.shutDownController = new AbortController()
88
75
  // make sure we don't make a lot of noise in the logs
89
76
  setMaxListeners(Infinity, this.shutDownController.signal)
77
+
78
+ this.running = false
90
79
  }
91
80
 
92
81
  isStarted (): boolean {
@@ -97,6 +86,10 @@ export class QueryManager implements Startable {
97
86
  * Starts the query manager
98
87
  */
99
88
  async start (): Promise<void> {
89
+ if (this.running) {
90
+ return
91
+ }
92
+
100
93
  this.running = true
101
94
 
102
95
  // allow us to stop queries on shut down
@@ -119,8 +112,6 @@ export class QueryManager implements Startable {
119
112
  throw new Error('QueryManager not started')
120
113
  }
121
114
 
122
- const stopQueryTimer = this.metrics.queryTime?.timer()
123
-
124
115
  if (options.signal == null) {
125
116
  // don't let queries run forever
126
117
  const signal = AbortSignal.timeout(DEFAULT_QUERY_TIMEOUT)
@@ -152,7 +143,6 @@ export class QueryManager implements Startable {
152
143
  const log = this.logger.forComponent(`${this.logPrefix}:query:` + uint8ArrayToString(key, 'base58btc'))
153
144
 
154
145
  // query a subset of peers up to `kBucketSize / 2` in length
155
- const startTime = Date.now()
156
146
  let queryFinished = false
157
147
 
158
148
  try {
@@ -165,7 +155,6 @@ export class QueryManager implements Startable {
165
155
  }
166
156
 
167
157
  log('query:start')
168
- this.metrics?.queries?.increment()
169
158
 
170
159
  const id = await convertBuffer(key)
171
160
  const peers = this.routingTable.closestPeers(id)
@@ -220,10 +209,6 @@ export class QueryManager implements Startable {
220
209
 
221
210
  queryFinished = true
222
211
  } catch (err: any) {
223
- if (!queryFinished) {
224
- this.metrics?.errors?.increment()
225
- }
226
-
227
212
  if (!this.running && err.name === 'QueryAbortedError') {
228
213
  // ignore query aborted errors that were thrown during query manager shutdown
229
214
  } else {
@@ -237,8 +222,7 @@ export class QueryManager implements Startable {
237
222
 
238
223
  signal.clear()
239
224
 
240
- stopQueryTimer?.()
241
- log('query:done in %dms', Date.now() - startTime)
225
+ log('query:done')
242
226
  }
243
227
  }
244
228
  }
package/src/query-self.ts CHANGED
@@ -6,6 +6,8 @@ import take from 'it-take'
6
6
  import pDefer from 'p-defer'
7
7
  import { pEvent } from 'p-event'
8
8
  import { QUERY_SELF_INTERVAL, QUERY_SELF_TIMEOUT, K, QUERY_SELF_INITIAL_INTERVAL } from './constants.js'
9
+ import { timeOperationMethod } from './utils.js'
10
+ import type { OperationMetrics } from './kad-dht.js'
9
11
  import type { PeerRouting } from './peer-routing/index.js'
10
12
  import type { RoutingTable } from './routing-table/index.js'
11
13
  import type { ComponentLogger, Logger, PeerId, Startable } from '@libp2p/interface'
@@ -20,6 +22,7 @@ export interface QuerySelfInit {
20
22
  initialInterval?: number
21
23
  queryTimeout?: number
22
24
  initialQuerySelfHasRun: DeferredPromise<void>
25
+ operationMetrics: OperationMetrics
23
26
  }
24
27
 
25
28
  export interface QuerySelfComponents {
@@ -39,37 +42,37 @@ export class QuerySelf implements Startable {
39
42
  private readonly interval: number
40
43
  private readonly initialInterval: number
41
44
  private readonly queryTimeout: number
42
- private started: boolean
45
+ private running: boolean
43
46
  private timeoutId?: ReturnType<typeof setTimeout>
44
47
  private controller?: AbortController
45
48
  private initialQuerySelfHasRun?: DeferredPromise<void>
46
49
  private querySelfPromise?: DeferredPromise<void>
47
50
 
48
51
  constructor (components: QuerySelfComponents, init: QuerySelfInit) {
49
- const { peerRouting, logPrefix, count, interval, queryTimeout, routingTable } = init
50
-
51
52
  this.peerId = components.peerId
52
- this.log = components.logger.forComponent(`${logPrefix}:query-self`)
53
- this.started = false
54
- this.peerRouting = peerRouting
55
- this.routingTable = routingTable
56
- this.count = count ?? K
57
- this.interval = interval ?? QUERY_SELF_INTERVAL
53
+ this.log = components.logger.forComponent(`${init.logPrefix}:query-self`)
54
+ this.running = false
55
+ this.peerRouting = init.peerRouting
56
+ this.routingTable = init.routingTable
57
+ this.count = init.count ?? K
58
+ this.interval = init.interval ?? QUERY_SELF_INTERVAL
58
59
  this.initialInterval = init.initialInterval ?? QUERY_SELF_INITIAL_INTERVAL
59
- this.queryTimeout = queryTimeout ?? QUERY_SELF_TIMEOUT
60
+ this.queryTimeout = init.queryTimeout ?? QUERY_SELF_TIMEOUT
60
61
  this.initialQuerySelfHasRun = init.initialQuerySelfHasRun
62
+
63
+ this.querySelf = timeOperationMethod(this.querySelf.bind(this), init.operationMetrics, 'SELF_QUERY')
61
64
  }
62
65
 
63
66
  isStarted (): boolean {
64
- return this.started
67
+ return this.running
65
68
  }
66
69
 
67
70
  start (): void {
68
- if (this.started) {
71
+ if (this.running) {
69
72
  return
70
73
  }
71
74
 
72
- this.started = true
75
+ this.running = true
73
76
  clearTimeout(this.timeoutId)
74
77
  this.timeoutId = setTimeout(() => {
75
78
  this.querySelf()
@@ -80,7 +83,7 @@ export class QuerySelf implements Startable {
80
83
  }
81
84
 
82
85
  stop (): void {
83
- this.started = false
86
+ this.running = false
84
87
 
85
88
  if (this.timeoutId != null) {
86
89
  clearTimeout(this.timeoutId)
@@ -92,7 +95,7 @@ export class QuerySelf implements Startable {
92
95
  }
93
96
 
94
97
  async querySelf (): Promise<void> {
95
- if (!this.started) {
98
+ if (!this.running) {
96
99
  this.log('skip self-query because we are not started')
97
100
  return
98
101
  }
@@ -104,7 +107,7 @@ export class QuerySelf implements Startable {
104
107
 
105
108
  this.querySelfPromise = pDefer()
106
109
 
107
- if (this.started) {
110
+ if (this.running) {
108
111
  this.controller = new AbortController()
109
112
  const signals = [this.controller.signal]
110
113
 
@@ -157,7 +160,7 @@ export class QuerySelf implements Startable {
157
160
  this.querySelfPromise.resolve()
158
161
  this.querySelfPromise = undefined
159
162
 
160
- if (!this.started) {
163
+ if (!this.running) {
161
164
  return
162
165
  }
163
166