-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proper handling of server stubs that throw? #2429
Comments
Not sure how much clean up you want to do, but if you want to change the error returned you can throw a SRE with the actual type you want. The reason the code catches and closes is because that is running on the executor thread that you provided. The exception would bubble up and then fall off the edge of the stack. (In theory that would be the UncaughtExceptionHandler, but by that point the code that threw it is far out of scope). ServerInterceptor has a ServerCallHandler, which can return a listener. You could hook that I think. I am not sure if it is possible to continue processing the RPC by that point though. |
I'm actually okay with the error returned, I'm mostly concerned with how to make sure I always get close or onCancel called in my interceptor. It looks like it's intentional this doesn't happen and I'm fine with that, I'm just kind of brainstorming the right way to recover here. It sounds like catching exceptions in onHalfClose and onMessage may be needed? |
This work?
|
Absolutely, and this is what I'm doing. But I'm having to do this per interceptor. I'm wondering if I can have a single interceptor that in catching the exception instead calls super.close(). It sounds like maybe this isn't advised to switch to a different chain and i should stick with the approach shown here per interceptor. |
Is the error handling the same per interceptor? Can you make interceptors extend an abstract interceptor? That would cut down on the boiler plate:
I think you are describing a hierarchical interception something, which I don't think exists in the model. |
Okay, here are two interceptors where I just added onHalfClose and onMessage handling to show what this looks like as it becomes more complete. To your point, there is a lambda in both of these cases I could be calling through an abstract base class, so I think I'll pursue that route.
and another example
Maybe what I'm asking for here is a well defined and single location that a "done" call will go through an interceptor. As it sits right now, there are a lot of possible exit points. |
So the interceptor should be able to listen to just onCancel and onCompleted. We do our best to guarantee one of those two methods will be called, and will be the last thing called. (I say "do our best" because interceptors can do anything, and if something throws in those methods there's not much we can do.) In this case though onCompleted is probably being called unexpectedly. While it's probably a good idea to handle onCompleted anyway (because another interceptor could maybe cause the same confusion), the fact onCompleted is being called in this case should be fixed as part of #3746. |
Please answer these questions before submitting your issue.
What version of gRPC are you using?
1.0.1
What JVM are you using (
java -version
)?1.8
What did you do?
If possible, provide a recipe for reproducing the error.
throw new RuntimeException()
in any server implementation of an rpc defined in your protoWhat did you expect to see?
client gets UNKNOWN, close or cancel to eventually be called in the interceptor chain on the server
What did you see instead?
client gets UNKNOWN, and my interceptor chain stops executing in the halfClose (for Unary requests/responses).
I'm wondering, if some interceptors want/need to do cleanup to do things like emit metrics, modify logging MDC in thread locals and such, what should I expect here and be doing? Is it reasonable to have an exception mapping interceptor that is the last one called right before the actual implementation and if it catches any exception translate it into a close(Status.UNKNOWN, new Metadata()) ? Should I instead have every interceptor catch exceptions in onHalfClose and onMessage and then bubble it after they do their personal cleanup? We had up to this point kept our cleanup logic isolated to close(...) and onCancel().
The text was updated successfully, but these errors were encountered: