process loops processing requests on an established stream.
(c frontendv1pb.Frontend_ProcessClient)
| 84 | |
| 85 | // process loops processing requests on an established stream. |
| 86 | func (fp *frontendProcessor) process(c frontendv1pb.Frontend_ProcessClient) error { |
| 87 | // Build a child context so we can cancel a query when the stream is closed. |
| 88 | ctx, cancel := context.WithCancel(c.Context()) |
| 89 | defer cancel() |
| 90 | |
| 91 | for { |
| 92 | request, err := c.Recv() |
| 93 | if err != nil { |
| 94 | return err |
| 95 | } |
| 96 | |
| 97 | switch request.Type { |
| 98 | case frontendv1pb.HTTP_REQUEST: |
| 99 | // Handle the request on a "background" goroutine, so we go back to |
| 100 | // blocking on c.Recv(). This allows us to detect the stream closing |
| 101 | // and cancel the query. We don't actually handle queries in parallel |
| 102 | // here, as we're running in lock step with the server - each Recv is |
| 103 | // paired with a Send. |
| 104 | go fp.runRequest(ctx, request.HttpRequest, request.StatsEnabled, func(response *httpgrpc.HTTPResponse, stats *querier_stats.QueryStats) error { |
| 105 | return c.Send(&frontendv1pb.ClientToFrontend{ |
| 106 | HttpResponse: response, |
| 107 | Stats: stats, |
| 108 | }) |
| 109 | }) |
| 110 | |
| 111 | case frontendv1pb.GET_ID: |
| 112 | err := c.Send(&frontendv1pb.ClientToFrontend{ClientID: fp.querierID}) |
| 113 | if err != nil { |
| 114 | return err |
| 115 | } |
| 116 | |
| 117 | default: |
| 118 | return fmt.Errorf("unknown request type: %v", request.Type) |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | func (fp *frontendProcessor) runRequest(ctx context.Context, request *httpgrpc.HTTPRequest, statsEnabled bool, sendHTTPResponse func(response *httpgrpc.HTTPResponse, stats *querier_stats.QueryStats) error) { |
| 124 | var stats *querier_stats.QueryStats |
no test coverage detected