Search code examples
c#exceptionthriftthrift-protocol

What is the Thrift equivalent of an http 500 response?


I am experimenting with a Thrift service using C#. With REST services, an uncaught exception will be translated by web frameworks into an HTTP 500 response code.

With thrift, as far as I can tell, I need to declare all possible exception types in my thrift file. That leaves me a two options that I can think of:

  1. Declare a InternalServerError type and add it to every single method. Every handler method will need to catch unhandled exceptions and rethrow my special type.
  2. Let the client experience the default behaviour in this case, which seems to be the socket closes unexpectedly.

The first option would work, but it seems to be a fair amount of runaround for what seems like a pretty common case. I notice there is a TApplicationException used internally which seems like it would work really well, except I can't seem to use it in my thrift files, so that won't work.

What is the idiomatic way thrift users handle uncaught exceptions on the server side?


Solution

  • HTTP 500

    With REST services, an uncaught exception will be translated by web frameworks into an HTTP 500 response code.

    That's an euphemism for "let the server call just fail miserably on uncaught exceptions". The REST frameworks follow these policies, because REST has been deliberately designed around HTTP verbs, responses and behaviour. So it is the other way round: HTTP status codes are not added somehow to a REST implementation, they are a basic principle of REST.

    Idiomatic exception handling

    What is the idiomatic way thrift users handle uncaught exceptions on the server side?

    Short answer: You don't wan't that.

    Uncaught exceptions are translated with some luck into generic TApplication exceptions, but they may also caught effects like unexpectedly closed transports, as you already observed. Obviously, the downside is, you loose all the information, context and exception details that you might want to transport to the client. Consequently, it is a good idea to have at least one kind of exception and add it to every service call, except oneway methods.

    Why not at oneway methods?

    Well, strictly speaking, you can add it too, the Thrift compiler will ignore it (newer versions emit a warning). In fact, since oneway methods are not returning any value ever, not even exceptions, the throws clause is completely useless with oneway.

    Isn't an exception handler too much overhead?

    The alternative would be to live with the unwanted behaviour explained above. But that's not how Thrift is designed, and will produce more pain than gain in the long run.

    it seems to be a fair amount of runaround for what seems like a pretty common case.

    Not really. With regard to coding, you have a minimal amount of additional work, that's true. But you should also have a look at what you get for that effort.

    Speaking generally, having an exception handler at any API facade (not limited to Thrift) is a good thing anyway. These exception handlers act as the last bastion and often serve additional purposes like logging, sanitizing security-relevant internas, and so on. And with regard to performance: Exceptions are costly, when they're raised. The pure existence of an exception handler does have only a very limited performance impact.

    Can I re-use TApplicationException, or derive from it?

    I notice there is a TApplicationException used internally which seems like it would work really well, except I can't seem to use it in my thrift files, so that won't work.

    TApplicationException is intended for internal use only, the same is true for TTransportException and TProtocolException. You also should not derive from them. Just declare your exception in the IDL file and let the Thrift compiler take care of the rest.