Skip to content

Commit d4dad9b

Browse files
authored
fix(kad-dht): run the periodic routing table refresh (libp2p#3538)
* test(kad-dht): cover the periodic routing table refresh These fail against the current code: the periodic (non-forced) refresh never issues queries, and a just-refreshed prefix length is not throttled. * fix(kad-dht): run the periodic routing table refresh Never-refreshed prefix lengths defaulted to the current time, so the throttle always skipped them and only the startup refresh ran. Default to the epoch and record refresh times on success.
1 parent bfb7ceb commit d4dad9b

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ export class RoutingTableRefresh {
148148

149149
this.log(`found ${peers} peers that were close to imaginary peer %p`, peerId)
150150
this.log('finished refreshing cpl %s with key %p (routing table size is now %s)', cpl, peerId, this.routingTable.size)
151+
152+
this.commonPrefixLengthRefreshedAt[cpl] = new Date()
151153
} finally {
152154
signal.clear()
153155
}
@@ -162,7 +164,7 @@ export class RoutingTableRefresh {
162164

163165
for (let i = 0; i <= maxCommonPrefix; i++) {
164166
// defaults to the zero value if we haven't refreshed it yet.
165-
dates[i] = this.commonPrefixLengthRefreshedAt[i] ?? new Date()
167+
dates[i] = this.commonPrefixLengthRefreshedAt[i] ?? new Date(0)
166168
}
167169

168170
return dates

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ import { MessageType } from '../src/message/dht.ts'
1717
import { peerResponseEvent } from '../src/query/events.ts'
1818
import { KAD_PEER_TAG_NAME, KAD_PEER_TAG_VALUE, RoutingTable } from '../src/routing-table/index.ts'
1919
import { isLeafBucket } from '../src/routing-table/k-bucket.ts'
20+
import { RoutingTableRefresh } from '../src/routing-table/refresh.ts'
2021
import * as kadUtils from '../src/utils.ts'
2122
import { createPeerIdWithPrivateKey, createPeerIdsWithPrivateKey } from './utils/create-peer-id.ts'
23+
import type { QueryEvent } from '../src/index.ts'
2224
import type { Network } from '../src/network.ts'
25+
import type { PeerRouting } from '../src/peer-routing/index.ts'
2326
import type { RoutingTableComponents } from '../src/routing-table/index.ts'
2427
import type { Bucket } from '../src/routing-table/k-bucket.ts'
2528
import type { Libp2pEvents, PeerId, PeerStore, Peer } from '@libp2p/interface'
@@ -572,6 +575,51 @@ describe('Routing Table', () => {
572575
expect(table.kb.root).to.have.property('peers').that.is.empty()
573576
})
574577

578+
describe('refresh', () => {
579+
let peerRouting: StubbedInstance<PeerRouting>
580+
let refresh: RoutingTableRefresh
581+
let queriedKeys: Uint8Array[]
582+
583+
beforeEach(() => {
584+
queriedKeys = []
585+
peerRouting = stubInterface<PeerRouting>()
586+
peerRouting.getClosestPeers.callsFake((key: Uint8Array) => {
587+
queriedKeys.push(key)
588+
return (async function * (): AsyncGenerator<QueryEvent> {})()
589+
})
590+
591+
refresh = new RoutingTableRefresh({ logger: defaultLogger() }, {
592+
peerRouting,
593+
routingTable: table,
594+
logPrefix: ''
595+
})
596+
})
597+
598+
afterEach(async () => {
599+
await refresh.stop()
600+
})
601+
602+
it('issues refresh queries when run without force (the periodic refresh path)', async () => {
603+
refresh.refreshTable(false)
604+
await delay(200)
605+
606+
expect(queriedKeys.length).to.be.greaterThan(0)
607+
})
608+
609+
it('does not re-query a common prefix length that was just refreshed', async () => {
610+
refresh.refreshTable(false)
611+
await delay(200)
612+
613+
const afterFirstRefresh = queriedKeys.length
614+
expect(afterFirstRefresh).to.be.greaterThan(0)
615+
616+
refresh.refreshTable(false)
617+
await delay(200)
618+
619+
expect(queriedKeys.length).to.equal(afterFirstRefresh)
620+
})
621+
})
622+
575623
describe('max size', () => {
576624
it('should constrain size to 10', async () => {
577625
const prefixLength = 8

0 commit comments

Comments
 (0)