Skip to content

Commit ce0e38d

Browse files
authored
fix: allow DHT self-query to time out (#2169)
When we run our first self-query we first check the routing table to see if it has peers. If not we wait for some peers to be discovered before continuing. The change here is to use the general query AbortSignal to abort waiting for peers to be discovered. If they are not discovered allow other queries to continue and fail with eaiser to understand error messages. Also fixes some logging typos and makes error messages more understandable.
1 parent 6850493 commit ce0e38d

File tree

6 files changed

+21
-35
lines changed

6 files changed

+21
-35
lines changed

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean {
103103

104104
// dns4 or dns6 or dnsaddr
105105
if (tuples[0][0] === DNS4_CODE || tuples[0][0] === DNS6_CODE || tuples[0][0] === DNSADDR_CODE) {
106-
log('%m is public %s', multiaddr, true)
107-
108106
return true
109107
}
110108

@@ -113,8 +111,6 @@ function multiaddrIsPublic (multiaddr: Multiaddr): boolean {
113111
const result = isPrivate(`${tuples[0][1]}`)
114112
const isPublic = result == null || !result
115113

116-
log('%m is public %s', multiaddr, isPublic)
117-
118114
return isPublic
119115
}
120116

@@ -170,13 +166,7 @@ export class DefaultDualKadDHT extends EventEmitter<PeerDiscoveryEvents> impleme
170166
components.events.addEventListener('self:peer:update', (evt) => {
171167
log('received update of self-peer info')
172168
const hasPublicAddress = evt.detail.peer.addresses
173-
.some(({ multiaddr }) => {
174-
const isPublic = multiaddrIsPublic(multiaddr)
175-
176-
log('%m is public %s', multiaddr, isPublic)
177-
178-
return isPublic
179-
})
169+
.some(({ multiaddr }) => multiaddrIsPublic(multiaddr))
180170

181171
this.getMode()
182172
.then(async mode => {

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ export class QuerySelf implements Startable {
105105

106106
this.querySelfPromise = pDefer()
107107

108-
if (this.routingTable.size === 0) {
109-
// wait to discover at least one DHT peer
110-
await pEvent(this.routingTable, 'peer:add')
111-
}
112-
113108
if (this.started) {
114109
this.controller = new AbortController()
115110
const signal = anySignal([this.controller.signal, AbortSignal.timeout(this.queryTimeout)])
@@ -122,7 +117,16 @@ export class QuerySelf implements Startable {
122117
} catch {} // fails on node < 15.4
123118

124119
try {
120+
if (this.routingTable.size === 0) {
121+
this.log('routing table was empty, waiting for some peers before running query')
122+
// wait to discover at least one DHT peer
123+
await pEvent(this.routingTable, 'peer:add', {
124+
signal
125+
})
126+
}
127+
125128
this.log('run self-query, look for %d peers timing out after %dms', this.count, this.queryTimeout)
129+
const start = Date.now()
126130

127131
const found = await pipe(
128132
this.peerRouting.getClosestPeers(this.components.peerId.toBytes(), {
@@ -133,16 +137,16 @@ export class QuerySelf implements Startable {
133137
async (source) => length(source)
134138
)
135139

136-
this.log('self-query ran successfully - found %d peers', found)
140+
this.log('self-query found %d peers in %dms', found, Date.now() - start)
141+
} catch (err: any) {
142+
this.log.error('self-query error', err)
143+
} finally {
144+
signal.clear()
137145

138146
if (this.initialQuerySelfHasRun != null) {
139147
this.initialQuerySelfHasRun.resolve()
140148
this.initialQuerySelfHasRun = undefined
141149
}
142-
} catch (err: any) {
143-
this.log.error('self-query error', err)
144-
} finally {
145-
signal.clear()
146150
}
147151
}
148152

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function bestRecord (selectors: Selectors, k: Uint8Array, records: Uint8A
2424
const selector = selectors[parts[1].toString()]
2525

2626
if (selector == null) {
27-
const errMsg = `Unrecognized key prefix: ${parts[1]}`
27+
const errMsg = `No selector function configured for key type "${parts[1]}"`
2828

2929
throw new CodeError(errMsg, 'ERR_UNRECOGNIZED_KEY_PREFIX')
3030
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function verifyRecord (validators: Validators, record: Libp2pRecord
2323
const validator = validators[parts[1].toString()]
2424

2525
if (validator == null) {
26-
const errMsg = 'Invalid record keytype'
26+
const errMsg = `No validator available for key type "${parts[1]}"`
2727

2828
throw new CodeError(errMsg, 'ERR_INVALID_RECORD_KEY_TYPE')
2929
}

packages/kad-dht/test/record/selection.spec.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,20 @@ describe('selection', () => {
1313
it('throws no records given when no records received', () => {
1414
expect(
1515
() => selection.bestRecord({}, uint8ArrayFromString('/'), [])
16-
).to.throw(
17-
/No records given/
18-
)
16+
).to.throw().with.property('code', 'ERR_NO_RECORDS_RECEIVED')
1917
})
2018

2119
it('throws on missing selector in the record key', () => {
2220
expect(
2321
() => selection.bestRecord({}, uint8ArrayFromString('/'), records)
24-
).to.throw(
25-
/Record key does not have a selector function/
26-
)
22+
).to.throw().with.property('code', 'ERR_NO_SELECTOR_FUNCTION_FOR_RECORD_KEY')
2723
})
2824

2925
it('throws on unknown key prefix', () => {
3026
expect(
3127
// @ts-expect-error invalid input
3228
() => selection.bestRecord({ world () {} }, uint8ArrayFromString('/hello/'), records)
33-
).to.throw(
34-
/Unrecognized key prefix: hello/
35-
)
29+
).to.throw().with.property('code', 'ERR_UNRECOGNIZED_KEY_PREFIX')
3630
})
3731

3832
it('returns the index from the matching selector', () => {

packages/kad-dht/test/record/validator.spec.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ describe('validator', () => {
8686
}
8787
}
8888
await expect(validator.verifyRecord(validators, rec))
89-
.to.eventually.rejectedWith(
90-
/Invalid record keytype/
91-
)
89+
.to.eventually.rejected.with.property('code', 'ERR_INVALID_RECORD_KEY_TYPE')
9290
})
9391
})
9492

0 commit comments

Comments
 (0)