@libp2p/kad-dht 14.0.2 → 14.1.0-32ca76fcb

Sign up to get free protection for your applications and to get access to all the features.
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