@@ -44,6 +44,10 @@ type selectQueryContext struct {
44
44
requestChannels []chan * qryResults
45
45
errorChannel chan error
46
46
wg sync.WaitGroup
47
+ createDFLock sync.Mutex
48
+ stopChan chan bool
49
+ queryWG sync.WaitGroup
50
+ finalErrorChan chan error
47
51
}
48
52
49
53
func (queryCtx * selectQueryContext ) start (parts []* partmgr.DBPartition , params * SelectParams ) (* frameIterator , error ) {
@@ -77,18 +81,21 @@ func (queryCtx *selectQueryContext) start(parts []*partmgr.DBPartition, params *
77
81
}
78
82
}
79
83
84
+ queryCtx .stopChan = make (chan bool , 1 )
85
+ queryCtx .finalErrorChan = make (chan error , 1 )
86
+ queryCtx .errorChannel = make (chan error , queryCtx .workers + len (queries ))
87
+
80
88
err = queryCtx .startCollectors ()
81
89
if err != nil {
82
90
return nil , err
83
91
}
84
92
85
93
for _ , query := range queries {
86
- err = queryCtx .processQueryResults (query )
87
- if err != nil {
88
- return nil , err
89
- }
94
+ queryCtx .queryWG .Add (1 )
95
+ go processQueryResults (queryCtx , query )
90
96
}
91
97
98
+ queryCtx .queryWG .Wait ()
92
99
for i := 0 ; i < queryCtx .workers ; i ++ {
93
100
close (queryCtx .requestChannels [i ])
94
101
}
@@ -98,7 +105,7 @@ func (queryCtx *selectQueryContext) start(parts []*partmgr.DBPartition, params *
98
105
close (queryCtx .errorChannel )
99
106
100
107
// return first error
101
- err = <- queryCtx .errorChannel
108
+ err = <- queryCtx .finalErrorChan
102
109
if err != nil {
103
110
return nil , err
104
111
}
@@ -260,7 +267,6 @@ func (queryCtx *selectQueryContext) parsePreAggregateLabels(partition *partmgr.D
260
267
func (queryCtx * selectQueryContext ) startCollectors () error {
261
268
262
269
queryCtx .requestChannels = make ([]chan * qryResults , queryCtx .workers )
263
- queryCtx .errorChannel = make (chan error , queryCtx .workers )
264
270
265
271
// Increment the WaitGroup counter.
266
272
queryCtx .wg .Add (queryCtx .workers )
@@ -274,27 +280,45 @@ func (queryCtx *selectQueryContext) startCollectors() error {
274
280
}(i )
275
281
}
276
282
283
+ // Watch error channel, and signal all go routines to stop in case of an error
284
+ go func () {
285
+ // Signal all goroutines to stop when error received
286
+ err , ok := <- queryCtx .errorChannel
287
+ if ok && err != nil {
288
+ close (queryCtx .stopChan )
289
+ queryCtx .finalErrorChan <- err
290
+ }
291
+
292
+ close (queryCtx .finalErrorChan )
293
+ return
294
+ }()
295
+
277
296
return nil
278
297
}
279
298
280
- func (queryCtx * selectQueryContext ) processQueryResults (query * partQuery ) error {
299
+ func processQueryResults (queryCtx * selectQueryContext , query * partQuery ) {
300
+ defer queryCtx .queryWG .Done ()
301
+
281
302
for query .Next () {
282
303
283
304
// read metric name
284
305
name , ok := query .GetField (config .MetricNameAttrName ).(string )
285
306
if ! ok {
286
- return fmt .Errorf ("could not find metric name attribute in response, res:%v" , query .GetFields ())
307
+ queryCtx .errorChannel <- fmt .Errorf ("could not find metric name attribute in response, res:%v" , query .GetFields ())
308
+ return
287
309
}
288
310
289
311
// read label set
290
312
lsetAttr , lok := query .GetField (config .LabelSetAttrName ).(string )
291
313
if ! lok {
292
- return fmt .Errorf ("could not find label set attribute in response, res:%v" , query .GetFields ())
314
+ queryCtx .errorChannel <- fmt .Errorf ("could not find label set attribute in response, res:%v" , query .GetFields ())
315
+ return
293
316
}
294
317
295
318
lset , err := utils .LabelsFromString (lsetAttr )
296
319
if err != nil {
297
- return err
320
+ queryCtx .errorChannel <- err
321
+ return
298
322
}
299
323
300
324
// read chunk encoding type
@@ -306,7 +330,8 @@ func (queryCtx *selectQueryContext) processQueryResults(query *partQuery) error
306
330
} else {
307
331
intEncoding , err := strconv .Atoi (encodingStr )
308
332
if err != nil {
309
- return fmt .Errorf ("error parsing encoding type of chunk, got: %v, error: %v" , encodingStr , err )
333
+ queryCtx .errorChannel <- fmt .Errorf ("error parsing encoding type of chunk, got: %v, error: %v" , encodingStr , err )
334
+ return
310
335
}
311
336
encoding = chunkenc .Encoding (intEncoding )
312
337
}
@@ -324,7 +349,8 @@ func (queryCtx *selectQueryContext) processQueryResults(query *partQuery) error
324
349
if labelValue != "" {
325
350
newLset [i ] = utils.Label {Name : trimmed , Value : labelValue }
326
351
} else {
327
- return fmt .Errorf ("no label named %v found to group by" , trimmed )
352
+ queryCtx .errorChannel <- fmt .Errorf ("no label named %v found to group by" , trimmed )
353
+ return
328
354
}
329
355
}
330
356
lset = newLset
@@ -336,6 +362,7 @@ func (queryCtx *selectQueryContext) processQueryResults(query *partQuery) error
336
362
hash = lset .Hash ()
337
363
}
338
364
365
+ queryCtx .createDFLock .Lock ()
339
366
// find or create data frame
340
367
frame , ok := queryCtx .dataFrames [hash ]
341
368
if ! ok {
@@ -349,19 +376,30 @@ func (queryCtx *selectQueryContext) processQueryResults(query *partQuery) error
349
376
results .IsServerAggregates (),
350
377
queryCtx .showAggregateLabel )
351
378
if err != nil {
352
- return err
379
+ queryCtx .errorChannel <- err
380
+ queryCtx .createDFLock .Unlock ()
381
+ return
353
382
}
354
383
queryCtx .dataFrames [hash ] = frame
355
384
queryCtx .frameList = append (queryCtx .frameList , frame )
356
385
}
386
+ queryCtx .createDFLock .Unlock ()
357
387
358
388
results .frame = frame
359
-
360
389
workerNum := hash & uint64 (queryCtx .workers - 1 )
361
- queryCtx .requestChannels [workerNum ] <- & results
390
+
391
+ // In case termination signal was received exit, Otherwise send query result to worker
392
+ select {
393
+ case _ = <- queryCtx .stopChan :
394
+ return
395
+ case queryCtx .requestChannels [workerNum ] <- & results :
396
+ }
397
+
362
398
}
363
399
364
- return query .Err ()
400
+ if query .Err () != nil {
401
+ queryCtx .errorChannel <- query .Err ()
402
+ }
365
403
}
366
404
367
405
func (queryCtx * selectQueryContext ) createColumnSpecs () ([]columnMeta , map [string ][]columnMeta , error ) {
0 commit comments