Skip to content

Commit 12bcd86

Browse files
authored
fix: tag kad-close peers with keepalive (#2740)
This will ensure we are always connected to peers in our root kad bucket. Also passes the complete set of options to the routing table to allow constraining memory usage from the constructor.
1 parent 4a14d4a commit 12bcd86

File tree

4 files changed

+30
-15
lines changed

4 files changed

+30
-15
lines changed

packages/kad-dht/src/index.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -397,12 +397,10 @@ export interface KadDHTInit {
397397
logPrefix?: string
398398

399399
/**
400-
* How long to wait in ms when pinging DHT peers to decide if they
401-
* should be evicted from the routing table or not.
402-
*
403-
* @default 10000
400+
* Settings for how long to wait in ms when pinging DHT peers to decide if
401+
* they should be evicted from the routing table or not.
404402
*/
405-
pingTimeout?: number
403+
pingTimeout?: Omit<AdaptiveTimeoutInit, 'metricsName' | 'metrics'>
406404

407405
/**
408406
* How many peers to ping in parallel when deciding if they should

packages/kad-dht/src/kad-dht.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ export class KadDHT extends TypedEventEmitter<PeerDiscoveryEvents> implements Ka
161161
pingTimeout,
162162
pingConcurrency,
163163
protocol: this.protocol,
164-
logPrefix: loggingPrefix
164+
logPrefix: loggingPrefix,
165+
prefixLength: init.prefixLength,
166+
splitThreshold: init.kBucketSplitThreshold
165167
})
166168

167169
this.providers = new Providers(components, providersInit ?? {})

packages/kad-dht/src/routing-table/index.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
import { InvalidMessageError, TypedEventEmitter } from '@libp2p/interface'
1+
import { InvalidMessageError, KEEP_ALIVE, TypedEventEmitter } from '@libp2p/interface'
22
import { PeerSet } from '@libp2p/peer-collections'
3+
import { AdaptiveTimeout } from '@libp2p/utils/adaptive-timeout'
34
import { PeerQueue } from '@libp2p/utils/peer-queue'
45
import { pbStream } from 'it-protobuf-stream'
56
import { Message, MessageType } from '../message/dht.js'
67
import * as utils from '../utils.js'
78
import { KBucket, isLeafBucket, type Bucket, type PingEventDetails } from './k-bucket.js'
89
import type { ComponentLogger, CounterGroup, Logger, Metric, Metrics, PeerId, PeerStore, Startable, Stream } from '@libp2p/interface'
910
import type { ConnectionManager } from '@libp2p/interface-internal'
11+
import type { AdaptiveTimeoutInit } from '@libp2p/utils/adaptive-timeout'
1012

1113
export const KAD_CLOSE_TAG_NAME = 'kad-close'
1214
export const KAD_CLOSE_TAG_VALUE = 50
1315
export const KBUCKET_SIZE = 20
1416
export const PREFIX_LENGTH = 32
15-
export const PING_TIMEOUT = 10000
16-
export const PING_CONCURRENCY = 10
17+
export const PING_TIMEOUT = 2000
18+
export const PING_CONCURRENCY = 20
1719

1820
export interface RoutingTableInit {
1921
logPrefix: string
2022
protocol: string
2123
prefixLength?: number
2224
splitThreshold?: number
2325
kBucketSize?: number
24-
pingTimeout?: number
26+
pingTimeout?: AdaptiveTimeoutInit
2527
pingConcurrency?: number
2628
tagName?: string
2729
tagValue?: number
@@ -53,7 +55,7 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
5355
private readonly components: RoutingTableComponents
5456
private readonly prefixLength: number
5557
private readonly splitThreshold: number
56-
private readonly pingTimeout: number
58+
private readonly pingTimeout: AdaptiveTimeout
5759
private readonly pingConcurrency: number
5860
private running: boolean
5961
private readonly protocol: string
@@ -73,7 +75,6 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
7375
this.components = components
7476
this.log = components.logger.forComponent(`${init.logPrefix}:routing-table`)
7577
this.kBucketSize = init.kBucketSize ?? KBUCKET_SIZE
76-
this.pingTimeout = init.pingTimeout ?? PING_TIMEOUT
7778
this.pingConcurrency = init.pingConcurrency ?? PING_CONCURRENCY
7879
this.running = false
7980
this.protocol = init.protocol
@@ -90,6 +91,11 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
9091
this.pingQueue.addEventListener('error', evt => {
9192
this.log.error('error pinging peer', evt.detail)
9293
})
94+
this.pingTimeout = new AdaptiveTimeout({
95+
...(init.pingTimeout ?? {}),
96+
metrics: this.components.metrics,
97+
metricName: `${init.logPrefix.replaceAll(':', '_')}_routing_table_ping_time_milliseconds`
98+
})
9399

94100
if (this.components.metrics != null) {
95101
this.metrics = {
@@ -177,6 +183,9 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
177183
tags: {
178184
[this.tagName]: {
179185
value: this.tagValue
186+
},
187+
[KEEP_ALIVE]: {
188+
value: 1
180189
}
181190
}
182191
})
@@ -185,7 +194,8 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
185194
for (const peer of removedPeers) {
186195
await this.components.peerStore.merge(peer, {
187196
tags: {
188-
[this.tagName]: undefined
197+
[this.tagName]: undefined,
198+
[KEEP_ALIVE]: undefined
189199
}
190200
})
191201
}
@@ -242,10 +252,11 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
242252

243253
return this.pingQueue.add(async () => {
244254
let stream: Stream | undefined
255+
const signal = this.pingTimeout.getTimeoutSignal()
245256

246257
try {
247258
const options = {
248-
signal: AbortSignal.timeout(this.pingTimeout)
259+
signal
249260
}
250261

251262
this.log('pinging old contact %p', oldContact.peerId)
@@ -278,6 +289,7 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
278289

279290
return false
280291
} finally {
292+
this.pingTimeout.cleanUp(signal)
281293
this.updateMetrics()
282294
}
283295
}, {

packages/kad-dht/test/routing-table.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-env mocha */
22

33
import { generateKeyPair } from '@libp2p/crypto/keys'
4-
import { TypedEventEmitter, stop, start } from '@libp2p/interface'
4+
import { TypedEventEmitter, stop, start, KEEP_ALIVE } from '@libp2p/interface'
55
import { mockConnectionManager } from '@libp2p/interface-compliance-tests/mocks'
66
import { defaultLogger } from '@libp2p/logger'
77
import { PeerSet } from '@libp2p/peer-collections'
@@ -251,6 +251,9 @@ describe('Routing Table', () => {
251251
expect(tagPeerSpy.getCall(0).args[1].tags).to.deep.equal({
252252
[KAD_CLOSE_TAG_NAME]: {
253253
value: KAD_CLOSE_TAG_VALUE
254+
},
255+
[KEEP_ALIVE]: {
256+
value: 1
254257
}
255258
})
256259
})

0 commit comments

Comments
 (0)