github.com/thanos-io/thanos@v0.32.5/internal/cortex/querier/queryrange/util.go (about) 1 // Copyright (c) The Cortex Authors. 2 // Licensed under the Apache License 2.0. 3 4 package queryrange 5 6 import ( 7 "context" 8 "net/http" 9 10 "github.com/weaveworks/common/httpgrpc" 11 12 "github.com/thanos-io/thanos/internal/cortex/tenant" 13 "github.com/thanos-io/thanos/internal/cortex/util/validation" 14 ) 15 16 // RequestResponse contains a request response and the respective request that was used. 17 type RequestResponse struct { 18 Request Request 19 Response Response 20 } 21 22 // DoRequests executes a list of requests in parallel. The limits parameters is used to limit parallelism per single request. 23 func DoRequests(ctx context.Context, downstream Handler, reqs []Request, limits Limits) ([]RequestResponse, error) { 24 tenantIDs, err := tenant.TenantIDs(ctx) 25 if err != nil { 26 return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error()) 27 } 28 29 // If one of the requests fail, we want to be able to cancel the rest of them. 30 ctx, cancel := context.WithCancel(ctx) 31 defer cancel() 32 33 // Feed all requests to a bounded intermediate channel to limit parallelism. 34 intermediate := make(chan Request) 35 go func() { 36 for _, req := range reqs { 37 intermediate <- req 38 } 39 close(intermediate) 40 }() 41 42 respChan, errChan := make(chan RequestResponse), make(chan error) 43 parallelism := validation.SmallestPositiveIntPerTenant(tenantIDs, limits.MaxQueryParallelism) 44 if parallelism > len(reqs) { 45 parallelism = len(reqs) 46 } 47 for i := 0; i < parallelism; i++ { 48 go func() { 49 for req := range intermediate { 50 resp, err := downstream.Do(ctx, req) 51 if err != nil { 52 errChan <- err 53 } else { 54 respChan <- RequestResponse{req, resp} 55 } 56 } 57 }() 58 } 59 60 resps := make([]RequestResponse, 0, len(reqs)) 61 var firstErr error 62 for range reqs { 63 select { 64 case resp := <-respChan: 65 resps = append(resps, resp) 66 case err := <-errChan: 67 if firstErr == nil { 68 cancel() 69 firstErr = err 70 } 71 } 72 } 73 74 return resps, firstErr 75 }