MCPcopy Create free account
hub / github.com/cortexproject/cortex / Process

Method Process

pkg/frontend/v1/frontend.go:230–324  ·  view source on GitHub ↗

Process allows backends to pull requests from the frontend.

(server frontendv1pb.Frontend_ProcessServer)

Source from the content-addressed store, hash-verified

228
229// Process allows backends to pull requests from the frontend.
230func (f *Frontend) Process(server frontendv1pb.Frontend_ProcessServer) error {
231 querierID, err := getQuerierID(server)
232 if err != nil {
233 return err
234 }
235
236 f.requestQueue.RegisterQuerierConnection(querierID)
237 defer f.requestQueue.UnregisterQuerierConnection(querierID)
238
239 // If the downstream request(from querier -> frontend) is cancelled,
240 // we need to ping the condition variable to unblock getNextRequestForQuerier.
241 // Ideally we'd have ctx aware condition variables...
242 go func() {
243 <-server.Context().Done()
244 f.requestQueue.QuerierDisconnecting()
245 }()
246
247 lastUserIndex := queue.FirstUser()
248
249 for {
250 reqWrapper, idx, err := f.requestQueue.GetNextRequestForQuerier(server.Context(), lastUserIndex, querierID)
251 if err != nil {
252 return err
253 }
254 lastUserIndex = idx
255
256 req := reqWrapper.(*request)
257
258 f.queueDuration.Observe(time.Since(req.enqueueTime).Seconds())
259 req.queueSpan.Finish()
260
261 /*
262 We want to dequeue the next unexpired request from the chosen tenant queue.
263 The chance of choosing a particular tenant for dequeueing is (1/active_tenants).
264 This is problematic under load, especially with other middleware enabled such as
265 querier.split-by-interval, where one request may fan out into many.
266 If expired requests aren't exhausted before checking another tenant, it would take
267 n_active_tenants * n_expired_requests_at_front_of_queue requests being processed
268 before an active request was handled for the tenant in question.
269 If this tenant meanwhile continued to queue requests,
270 it's possible that it's own queue would perpetually contain only expired requests.
271 */
272 if req.originalCtx.Err() != nil {
273 lastUserIndex = lastUserIndex.ReuseLastUser()
274 continue
275 }
276
277 // Handle the stream sending & receiving on a goroutine so we can
278 // monitoring the contexts in a select and cancel things appropriately.
279 resps := make(chan *frontendv1pb.ClientToFrontend, 1)
280 errs := make(chan error, 1)
281 go func() {
282 err = server.Send(&frontendv1pb.FrontendToClient{
283 Type: frontendv1pb.HTTP_REQUEST,
284 HttpRequest: req.request,
285 StatsEnabled: stats.IsEnabled(req.originalCtx),
286 })
287 if err != nil {

Callers

nothing calls this directly

Calls 15

FirstUserFunction · 0.92
IsEnabledFunction · 0.92
FromContextFunction · 0.92
getQuerierIDFunction · 0.85
DoneMethod · 0.80
QuerierDisconnectingMethod · 0.80
FinishMethod · 0.80
ReuseLastUserMethod · 0.80

Tested by

no test coverage detected