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

Method FrontendLoop

pkg/scheduler/scheduler.go:222–296  ·  view source on GitHub ↗

FrontendLoop handles connection from frontend.

(frontend schedulerpb.SchedulerForFrontend_FrontendLoopServer)

Source from the content-addressed store, hash-verified

220
221// FrontendLoop handles connection from frontend.
222func (s *Scheduler) FrontendLoop(frontend schedulerpb.SchedulerForFrontend_FrontendLoopServer) error {
223 frontendAddress, frontendCtx, err := s.frontendConnected(frontend)
224 if err != nil {
225 return err
226 }
227 defer s.frontendDisconnected(frontendAddress)
228
229 // Response to INIT. If scheduler is not running, we skip for-loop, send SHUTTING_DOWN and exit this method.
230 if s.State() == services.Running {
231 if err := frontend.Send(&schedulerpb.SchedulerToFrontend{Status: schedulerpb.OK}); err != nil {
232 return err
233 }
234 }
235
236 // We stop accepting new queries in Stopping state. By returning quickly, we disconnect frontends, which in turns
237 // cancels all their queries.
238 for s.State() == services.Running {
239 msg, err := frontend.Recv()
240 if err != nil {
241 // No need to report this as error, it is expected when query-frontend performs SendClose() (as frontendSchedulerWorker does).
242 if err == io.EOF {
243 return nil
244 }
245 return err
246 }
247
248 if s.State() != services.Running {
249 break // break out of the loop, and send SHUTTING_DOWN message.
250 }
251
252 var resp *schedulerpb.SchedulerToFrontend
253
254 switch msg.GetType() {
255 case schedulerpb.ENQUEUE:
256
257 // If there is a logical plan in the request body, we will fragment it before enqueueing
258 // otherwise, it will be a single request and is the root and can be enqueued directly
259 byteLP, err := getPlanFromHTTPRequest(msg.HttpRequest)
260 if err != nil {
261 return err
262 }
263 if len(byteLP) != 0 {
264 err = s.fragmentAndEnqueueRequest(frontendCtx, frontendAddress, msg, byteLP)
265 } else {
266 err = s.enqueueRequest(frontendCtx, frontendAddress, msg, plan_fragments.Fragment{FragmentID: 0, IsRoot: true})
267 }
268
269 switch err {
270 case nil:
271 resp = &schedulerpb.SchedulerToFrontend{Status: schedulerpb.OK}
272 case queue.ErrTooManyRequests:
273 resp = &schedulerpb.SchedulerToFrontend{Status: schedulerpb.TOO_MANY_REQUESTS_PER_TENANT}
274 default:
275 resp = &schedulerpb.SchedulerToFrontend{Status: schedulerpb.ERROR, Error: err.Error()}
276 }
277
278 case schedulerpb.CANCEL:
279 s.cancelRequestAndRemoveFromPending(frontendAddress, msg.QueryID, 0, true)

Callers

nothing calls this directly

Calls 12

frontendConnectedMethod · 0.95
frontendDisconnectedMethod · 0.95
enqueueRequestMethod · 0.95
getPlanFromHTTPRequestFunction · 0.85
StateMethod · 0.65
SendMethod · 0.65
RecvMethod · 0.65
GetTypeMethod · 0.45
ErrorMethod · 0.45
LogMethod · 0.45

Tested by

no test coverage detected