@@ -19,7 +19,7 @@ import { QueryManager, type QueryManagerInit } from '../src/query/manager.js'
19
19
import { convertBuffer } from '../src/utils.js'
20
20
import { createPeerId , createPeerIds } from './utils/create-peer-id.js'
21
21
import { sortClosestPeers } from './utils/sort-closest-peers.js'
22
- import type { QueryFunc } from '../src/query/types.js'
22
+ import type { QueryContext , QueryFunc } from '../src/query/types.js'
23
23
import type { RoutingTable } from '../src/routing-table/index.js'
24
24
import type { PeerId } from '@libp2p/interface'
25
25
@@ -29,12 +29,9 @@ interface TopologyEntry {
29
29
value ?: Uint8Array
30
30
closerPeers ?: number [ ]
31
31
event : QueryEvent
32
+ context ?: QueryContext
32
33
}
33
- type Topology = Record < string , {
34
- delay ?: number | undefined
35
- error ?: Error | undefined
36
- event : QueryEvent
37
- } >
34
+ type Topology = Record < string , TopologyEntry >
38
35
39
36
describe ( 'QueryManager' , ( ) => {
40
37
let ourPeerId : PeerId
@@ -55,7 +52,7 @@ describe('QueryManager', () => {
55
52
}
56
53
57
54
function createTopology ( opts : Record < number , { delay ?: number , error ?: Error , value ?: Uint8Array , closerPeers ?: number [ ] } > ) : Topology {
58
- const topology : Record < string , { delay ?: number , error ?: Error , event : QueryEvent } > = { }
55
+ const topology : Topology = { }
59
56
60
57
Object . keys ( opts ) . forEach ( key => {
61
58
const id = parseInt ( key )
@@ -94,9 +91,12 @@ describe('QueryManager', () => {
94
91
return topology
95
92
}
96
93
97
- function createQueryFunction ( topology : Record < string , { delay ?: number , event : QueryEvent } > ) : QueryFunc {
98
- const queryFunc : QueryFunc = async function * ( { peer } ) {
94
+ function createQueryFunction ( topology : Topology ) : QueryFunc {
95
+ const queryFunc : QueryFunc = async function * ( context ) {
96
+ const { peer } = context
97
+
99
98
const res = topology [ peer . toString ( ) ]
99
+ res . context = context
100
100
101
101
if ( res . delay != null ) {
102
102
await delay ( res . delay )
@@ -870,4 +870,43 @@ describe('QueryManager', () => {
870
870
871
871
await manager . stop ( )
872
872
} )
873
+
874
+ it ( 'should abort the query if we break out of the loop early' , async ( ) => {
875
+ const manager = new QueryManager ( {
876
+ peerId : ourPeerId ,
877
+ logger : defaultLogger ( )
878
+ } , {
879
+ ...defaultInit ( ) ,
880
+ disjointPaths : 2
881
+ } )
882
+ await manager . start ( )
883
+
884
+ // 1 -> 0 [pathComplete]
885
+ // 4 -> 3 [delay] -> 2 [pathComplete]
886
+ const topology = createTopology ( {
887
+ // quick value path
888
+ 0 : { value : uint8ArrayFromString ( 'true' ) } ,
889
+ 1 : { closerPeers : [ 0 ] } ,
890
+ // slow value path
891
+ 2 : { value : uint8ArrayFromString ( 'true' ) } ,
892
+ 3 : { delay : 100 , closerPeers : [ 2 ] } ,
893
+ 4 : { closerPeers : [ 3 ] }
894
+ } )
895
+
896
+ routingTable . closestPeers . returns ( [ peers [ 1 ] , peers [ 4 ] ] )
897
+
898
+ for await ( const event of manager . run ( key , createQueryFunction ( topology ) ) ) {
899
+ if ( event . name === 'VALUE' ) {
900
+ expect ( event . from . toString ( ) ) . to . equal ( peers [ 0 ] . toString ( ) )
901
+
902
+ // break out of loop early
903
+ break
904
+ }
905
+ }
906
+
907
+ // should have aborted query on slow path
908
+ expect ( topology [ peers [ 3 ] . toString ( ) ] ) . to . have . nested . property ( 'context.signal.aborted' , true )
909
+
910
+ await manager . stop ( )
911
+ } )
873
912
} )
0 commit comments