diff --git a/tests/waku_store/test_client.nim b/tests/waku_store/test_client.nim index ec462eb56..d9c94a10c 100644 --- a/tests/waku_store/test_client.nim +++ b/tests/waku_store/test_client.nim @@ -1,6 +1,6 @@ {.used.} -import std/options, testutils/unittests, chronos, libp2p/crypto/crypto +import std/[options, sets], testutils/unittests, chronos, libp2p/crypto/crypto import waku/[node/peer_manager, waku_core, waku_store, waku_store/client, common/paging], @@ -223,3 +223,24 @@ suite "Store Client": not await handlerFuture.withTimeout(FUTURE_TIMEOUT) queryResponse.isErr() queryResponse.error.kind == ErrorCode.PEER_DIAL_FAILURE + + asyncTest "queryToAny shuffles peers across calls": + # Register several fake store peers (no servers running) so every dial + # fails. PEER_DIAL_FAILURE carries the peerId of the last peer tried in + # the shuffled order, so observing different "last" peerIds across calls + # confirms shuffle is active inside queryToAny. + for _ in 0 ..< 3: + let fakeSwitch = newTestSwitch() + let peerInfo = fakeSwitch.peerInfo.toRemotePeerInfo() + peerInfo.protocols = @[WakuStoreCodec] + clientSwitch.peerStore.addPeer(peerInfo) + + var observedLastPeers: HashSet[string] + for _ in 0 ..< 20: + let res = await client.queryToAny(storeQuery) + check: + res.isErr() + res.error.kind == ErrorCode.PEER_DIAL_FAILURE + observedLastPeers.incl(res.error.address) + + check observedLastPeers.len >= 2 diff --git a/waku/waku_store/client.nim b/waku/waku_store/client.nim index 9b26d44a8..b49662811 100644 --- a/waku/waku_store/client.nim +++ b/waku/waku_store/client.nim @@ -1,7 +1,7 @@ {.push raises: [].} import - std/[options, tables, sequtils, algorithm], + std/[options, tables, sequtils, algorithm, random], results, chronicles, chronos, @@ -100,7 +100,8 @@ proc queryToAny*( if peers.len == 0: return err(StoreError(kind: BAD_RESPONSE, cause: "no service store peer connected")) - # Shuffle to distribute load and limit retries + # Shuffle to distribute load across store peers and limit retries + shuffle(peers) let peersToTry = peers[0 ..< min(peers.len, MaxQueryRetries)] var lastError: StoreError