@@ -306,7 +306,7 @@ func (s *Server) peerQuery(ctx context.Context, data cluster.Traceable, name, pa
306
306
// across the cluster, except to the local peer. If any peer fails requests to
307
307
// other peers are aborted. If enough peers have been heard from (based on
308
308
// speculation-threshold configuration), and we are missing the others, try to
309
- // speculatively query other members of the shard group.
309
+ // speculatively query each other member of each shard group.
310
310
// ctx: request context
311
311
// data: request to be submitted
312
312
// name: name to be used in logging & tracing
@@ -323,7 +323,6 @@ func (s *Server) peerQuerySpeculative(ctx context.Context, data cluster.Traceabl
323
323
defer cancel ()
324
324
325
325
originalPeers := make (map [string ]struct {}, len (peerGroups ))
326
- pendingResponses := make (map [int32 ]struct {}, len (peerGroups ))
327
326
receivedResponses := make (map [int32 ]struct {}, len (peerGroups ))
328
327
329
328
responses := make (chan struct {
@@ -357,15 +356,20 @@ func (s *Server) peerQuerySpeculative(ctx context.Context, data cluster.Traceabl
357
356
for group , peers := range peerGroups {
358
357
peer := peers [0 ]
359
358
originalPeers [peer .GetName ()] = struct {}{}
360
- pendingResponses [group ] = struct {}{}
361
359
go askPeer (group , peer )
362
360
}
363
361
364
362
result := make (map [string ]PeerResponse )
365
363
366
- specCheckTicker := time .NewTicker (5 * time .Millisecond )
364
+ var ticker * time.Ticker
365
+ var tickChan <- chan time.Time
366
+ if speculationThreshold != 1 {
367
+ ticker = time .NewTicker (5 * time .Millisecond )
368
+ tickChan = ticker .C
369
+ defer ticker .Stop ()
370
+ }
367
371
368
- for len (pendingResponses ) > 0 {
372
+ for len (receivedResponses ) < len ( peerGroups ) {
369
373
select {
370
374
case resp := <- responses :
371
375
if _ , ok := receivedResponses [resp .shardGroup ]; ok {
@@ -379,18 +383,20 @@ func (s *Server) peerQuerySpeculative(ctx context.Context, data cluster.Traceabl
379
383
380
384
result [resp .data .peer .GetName ()] = resp .data
381
385
receivedResponses [resp .shardGroup ] = struct {}{}
382
- delete (pendingResponses , resp .shardGroup )
383
386
delete (originalPeers , resp .data .peer .GetName ())
384
387
385
- case <- specCheckTicker . C :
388
+ case <- tickChan :
386
389
// Check if it's time to speculate!
387
- percentReceived := 1 - ( float64 (len (pendingResponses )) / float64 (len (peerGroups ) ))
388
- if percentReceived > speculationThreshold {
390
+ percentReceived := float64 (len (receivedResponses )) / float64 (len (peerGroups ))
391
+ if percentReceived >= speculationThreshold {
389
392
// kick off speculative queries to other members now
390
- specCheckTicker .Stop ()
393
+ ticker .Stop ()
391
394
speculativeAttempts .Inc ()
392
- for shardGroup := range pendingResponses {
393
- eligiblePeers := peerGroups [shardGroup ][1 :]
395
+ for shardGroup , peers := range peerGroups {
396
+ if _ , ok := receivedResponses [shardGroup ]; ok {
397
+ continue
398
+ }
399
+ eligiblePeers := peers [1 :]
394
400
for _ , peer := range eligiblePeers {
395
401
speculativeRequests .Inc ()
396
402
go askPeer (shardGroup , peer )
0 commit comments