MCPcopy
hub / github.com/grafana/dskit / TapHandle

Method TapHandle

server/limits.go:63–88  ·  view source on GitHub ↗

TapHandle is called after receiving grpc request and headers, but before reading any request data yet. If we reject request here (by returning non-nil error), it won't be counted towards any metrics (eg. in middleware.grpcStatsHandler). If we accept request (no error), the request should be processe

(ctx context.Context, info *tap.Info)

Source from the content-addressed store, hash-verified

61// If we accept request (no error), the request should be processed and eventually HandleRPC with stats.End notification will be called,
62// unless the context is cancelled before we start processing the request.
63func (g *grpcInflightLimitCheck) TapHandle(ctx context.Context, info *tap.Info) (context.Context, error) {
64 if !isMethodNameValid(info.FullMethodName) {
65 // If method name is not valid, we let the request continue, but not call method limiter.
66 // Otherwise, we would not be able to call method limiter again when the call finishes, because in this case grpc server will not call stat handler.
67 return ctx, nil
68 }
69
70 ctx, err := g.methodLimiter.RPCCallStarting(ctx, info.FullMethodName, info.Header)
71 if err != nil {
72 return ctx, err
73 }
74
75 // We called RPCCallStarting, so we need to ensure RPCCallFinished is called once the request is done.
76 // Because of a shortcut introduced in https://github.com/grpc/grpc-go/pull/8439 this may not happen.
77 // We could create a goroutine that would watch ctx.Done() and call RPCCallFinished if the context is done and we have not started processing the headers yet.
78 // However, that would mean paying the cost of an extra goroutine for every single gRPC request, just in case the request's context is cancelled before we start processing it.
79 // Instead of that we schedule a cheaper timer that we will cancel in the happy case, which will run after 10s and perform the cleanup only when needed.
80 state := &gprcInflightLimitCheckerState{
81 fullMethod: info.FullMethodName,
82 timestamp: time.Now(),
83 headersProcessed: make(chan struct{}),
84 }
85 state.nonProcessedRequestTimer = g.timeAfterFunc(unprocessedRequestCheckTimeout, g.checkProbablyEarlyAbortedRequest(ctx, state))
86
87 return context.WithValue(ctx, gprcInflightLimitCheckerStateKey{}, state), nil
88}
89
90func (g *grpcInflightLimitCheck) checkProbablyEarlyAbortedRequest(ctx context.Context, state *gprcInflightLimitCheckerState) func() {
91 return func() {

Callers

nothing calls this directly

Calls 4

timeAfterFuncMethod · 0.95
isMethodNameValidFunction · 0.85
RPCCallStartingMethod · 0.65

Tested by

no test coverage detected