[
https://issues.apache.org/jira/browse/THRIFT-2908?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14254917#comment-14254917
]
Adam Hawkins commented on THRIFT-2908:
--------------------------------------
Thanks for the quick response. I've prepared some small code examples to make
sure you and I are communicating correctly. Here's an example Thrift IDL file.
{code:title=echo_service.thrift}
service EchoService {
string echo(1: string message)
void explode()
}
{code}
Here's a snippet from the generated {{echo_service.thrift}} file.
{code:title=echo_service.rb}
class Processor
include ::Thrift::Processor
def process_echo(seqid, iprot, oprot)
args = read_args(iprot, Echo_args)
result = Echo_result.new()
result.success = @handler.echo(args.message)
write_result(result, oprot, 'echo', seqid)
end
def process_explode(seqid, iprot, oprot)
args = read_args(iprot, Explode_args)
result = Explode_result.new()
@handler.explode()
write_result(result, oprot, 'explode', seqid)
end
end
{code}
There is no exception handling there. Now if I modify the IDL to throw an
exception like so:
{code:thrift}
exception EchoException { }
service EchoService {
string echo(1: string message)
throws (1: EchoException noEcho)
void explode()
}
{code}
The resulting processor code now includes appropriate {{rescue}} clauses based
off the IDL.
{code:ruby}
class Processor
include ::Thrift::Processor
def process_echo(seqid, iprot, oprot)
args = read_args(iprot, Echo_args)
result = Echo_result.new()
begin
result.success = @handler.echo(args.message)
rescue ::EchoException => noEcho
result.noEcho = noEcho
end
write_result(result, oprot, 'echo', seqid)
end
def process_explode(seqid, iprot, oprot)
args = read_args(iprot, Explode_args)
result = Explode_result.new()
@handler.explode()
write_result(result, oprot, 'explode', seqid)
end
end
{code}
This is where my confusion begins and hopefully we can clear that up. Now it's
time to implement this {{EchoService}} in ruby. An example handler would be:
{code:ruby}
class Handler
def echo(string)
string
end
end
{code}
This this is a correct implementation and will behave correctly with the thrift
servers in the ruby library. Now if the {{Handler}} class is implemented
incorrectly like so:
{code:ruby}
class Handler
def echo(string)
nil
end
end
{code}
The client would raise/throw a {{TApplicationException}} because the server did
not return the correct type ({{NilClass}} instead of a {{String}}). This is the
correct and expected behavior based on my reading. Now if we change the handler
to fail in a different way.
{code:ruby}
class Handler
def echo(string)
fail "Unexpected error!"
end
end
{code}
If a client calls the {{echo}} RPC the server will fail in different ways.
Using the thread pool server, the thread handling that RPC dies and exits. The
client receives a {{TTransportException}} and if uncaught the process exits.
It's my understanding that we should be able to wrap all the service handlers
in something like:
{code:ruby}
class Handler
def echo(string)
# do something
rescue => ex
raise Thrift::ApplicationException.new(Thrift::Application::INTERNAL_ERROR,
ex.to_s)
end
end
{code}
Then the thrift library can communicate that failure to the clients and they'll
receive a {{TApplicationException}} and react accordingly. However this is not
currently the case. Throwing the {{Thrift::ApplicationException}} or returning
it has no impact on what the client receives, it receives a
{{TTransportException}} in both cases. Is this the correct behavior or should I
be able to wrap my calls to catch exceptions and forward them as
{{TApplicationException}} to clients?
> Limited use Thrift::ApplicationException in Ruby
> ------------------------------------------------
>
> Key: THRIFT-2908
> URL: https://issues.apache.org/jira/browse/THRIFT-2908
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Library
> Affects Versions: 0.9.2
> Reporter: Adam Hawkins
>
> I'm implementing a bunch of Thrift servers in Ruby. I'm trying to figure out
> how to use {{Thrift::ApplicationException}} for error handling. I came across
> a link on stack overflow
> [http://stackoverflow.com/questions/27312244/general-error-handling-in-apache-thrift]
> that documents exactly what I'm trying to do but applied to the delphi
> library. The fix (THRIFT-2860) has been merged and set for 0.9.3 release. I'm
> investigating the generated ruby code and it seems
> {{Thrift::ApplicationException}} is only used in the clients, and never
> mentioned in any of the server or processor code. Is it possible to implement
> a similar fix for ruby severs, or should I define a generic exception and
> have all RPC's throw that as a work around?
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)