@@ -302,6 +302,106 @@ func TestWorkManagerWorkDispatcherFailures(t *testing.T) {
302302 }
303303}
304304
305+ // TestWorkManagerErrQueryTimeout tests that the workers that return query
306+ // timeout are not sent jobs until they return a different error.
307+ func TestWorkManagerErrQueryTimeout (t * testing.T ) {
308+ const numQueries = 2
309+ const numWorkers = 1
310+
311+ // Start work manager.
312+ wm , workers := startWorkManager (t , numWorkers )
313+
314+ // When the jobs gets scheduled, keep track of which worker was
315+ // assigned the job.
316+ type sched struct {
317+ wk * mockWorker
318+ job * queryJob
319+ }
320+
321+ // Schedule a batch of queries.
322+ var scheduledJobs [numQueries ]chan sched
323+ var queries [numQueries ]* Request
324+ for i := 0 ; i < numQueries ; i ++ {
325+ q := & Request {
326+ Req : & mockQueryEncoded {},
327+ }
328+ queries [i ] = q
329+ scheduledJobs [i ] = make (chan sched )
330+ }
331+
332+ // Fot each worker, spin up a goroutine that will forward the job it
333+ // got to our slice of scheduled jobs, such that we can handle them in
334+ // order.
335+ for i := 0 ; i < len (workers ); i ++ {
336+ wk := workers [i ]
337+ go func () {
338+ for {
339+ job := <- wk .nextJob
340+ scheduledJobs [int (job .index )] <- sched {
341+ wk : wk ,
342+ job : job ,
343+ }
344+ }
345+ }()
346+ }
347+
348+ // Send the batch, and Retrieve all jobs immediately.
349+ errChan := wm .Query (queries [:])
350+
351+ var iter int
352+ var s sched
353+ for i := 0 ; i < numQueries ; i ++ {
354+ select {
355+ case s = <- scheduledJobs [i ]:
356+ if s .job .index != float64 (i ) {
357+ t .Fatalf ("wrong index" )
358+ }
359+ if iter == 1 {
360+ t .Fatalf ("Expected only one scheduled job" )
361+ }
362+ iter ++
363+ case <- errChan :
364+ t .Fatalf ("did not expect on errChan" )
365+ case <- time .After (time .Second ):
366+ if iter < 1 {
367+ t .Fatalf ("next job not received" )
368+ }
369+ }
370+ }
371+
372+ select {
373+ case s .wk .results <- & jobResult {
374+ job : s .job ,
375+ err : ErrQueryTimeout ,
376+ }:
377+ case <- errChan :
378+ t .Fatalf ("did not expect on errChan" )
379+ case <- time .After (time .Second ):
380+ t .Fatalf ("result not handled" )
381+ }
382+
383+ // Finally, make sure the job is not retried as there are no available
384+ // peer to retry it.
385+
386+ select {
387+ case <- scheduledJobs [0 ]:
388+ t .Fatalf ("did not expect job rescheduled" )
389+ case <- errChan :
390+ t .Fatalf ("did not expect on errChan" )
391+ case <- time .After (time .Second ):
392+ }
393+
394+ // There should be no errChan message as query is still incomplete.
395+ select {
396+ case err := <- errChan :
397+ if err != nil {
398+ t .Fatalf ("got error: %v" , err )
399+ }
400+ t .Fatalf ("expected no errChan message" )
401+ case <- time .After (time .Second ):
402+ }
403+ }
404+
305405// TestWorkManagerCancelBatch checks that we can cancel a batch query midway,
306406// and that the jobs it contains are canceled.
307407func TestWorkManagerCancelBatch (t * testing.T ) {
0 commit comments