gRPC Context return null when I use SimpleForwardingServerCallListener

1.1k Views Asked by At

I want to override sendMessage, sendHeaders, onMessage, onHalfClose methods in ServerInterceptor (with Context):

val context = Context.current().withValue(TestConstants.CONTEXT_KEY, "testValue1")
val delegatedCall = object : SimpleForwardingServerCall<ReqT, RespT>(call) {

    override fun sendMessage(message: RespT) {
        [email protected](message)
        super.sendMessage(message)
    }

    override fun sendHeaders(headers: Metadata) {
        [email protected](headers)
        super.sendHeaders(headers)
    }

    override fun close(status: Status, trailers: Metadata) {
        [email protected](status, trailers)
        super.close(status, trailers)
    }
}
val delegatedListener: ServerCall.Listener<ReqT> =
    if (context === null)
        next.startCall(delegatedCall, headers)
    else
        Contexts.interceptCall(context, delegatedCall, headers, next)

return object : ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(delegatedListener) {

    override fun onMessage(message: ReqT) {
        [email protected](message, headers)
        super.onMessage(message)
    }

    override fun onHalfClose() {
        [email protected](headers)
        super.onHalfClose()
    }

    override fun onCancel() {
        [email protected](headers)
        super.onCancel()
    }

    override fun onComplete() {
        [email protected](headers)
        super.onComplete()
    }

    override fun onReady() {
        [email protected](headers)
        super.onReady()
    }
}

Here is the output:

>>>>intercept1
>>>>intercept2: testValue1
>>>>onReady1: null
>>>>onMessage1: null
>>>>onHalfClose1: null
HelloService3.hello: testValue1
>>>>sendHeaders2: testValue1
>>>>sendHeaders1: testValue1
>>>>sendMessage2: testValue1
>>>>sendMessage1: testValue1

You can see that Context is valid for delegatedCall(sendMessage, sendHeaders) but invalid for delegatedListener(onMessage, onHalfClose).

Why and how to solve this problem?

1

There are 1 best solutions below

0
On

I believe the problem is that that specific SimpleForwardingServerCallListener isn't seeing the change because it is executed before the listener within Contexts.interceptCall(). The Listener is used for callbacks, so they are called by gRPC. gRPC will call the listener returned, and that listener will end up calling delegatedListener and delegatedListener is the one that does the Context adjusting. Contexts.interceptCall() doesn't change call at all, so the fact that the calls see the Context means that the Listener must be working correctly.

I suggest making a ServerCallHandler that does all the calls to SimpleServerInterceptor and passing that handler to Contexts.interceptCall().

(Just a sketch, since I am not familiar with Kotlin)

val context = Context.current().withValue(TestConstants.CONTEXT_KEY, "testValue1")
if (context === null) // Unclear how this will be null
    return next.startCall(delegatedCall, headers)
else
    return Contexts.interceptCall(context, delegatedCall, headers, new SimpleServerInterceptorHandler(next))

...

// Within SimpleServerInterceptorHandler
val delegatedCall = object : SimpleForwardingServerCall<ReqT, RespT>(call) {
  ...
}
val delegatedListener: ServerCall.Listener<ReqT> =
        next.startCall(delegatedCall, headers)
return object : ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(delegatedListener) {
  ...
}