You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "Peter Sanford (Updated) (JIRA)" <ji...@apache.org> on 2011/11/17 00:07:51 UTC

[jira] [Updated] (THRIFT-146) Make Thrift EventMachine Compatible

     [ https://issues.apache.org/jira/browse/THRIFT-146?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Peter Sanford updated THRIFT-146:
---------------------------------

    Attachment: 0015-Added-EventMachine-tutorial-example.patch
                0014-Eventmachine-spec-cleanup-for-ruby-1.8.patch
                0013-Added-timeout-option-to-eventmachine-transport.patch
                0012-Eventmachine-triggers-errback-on-connect-errors.patch
                0011-Added-eventmachine-test-for-void-functions.patch
                0010-Added-test-for-oneway-functions-with-eventmachine.patch
                0009-Added-an-asnyc-test-for-EventMachine.patch
                0008-Initial-event-machine-test.patch
                0007-Generate-eventmachine-bindings-for-tests.patch
                0006-Added-eventmachine-as-a-dev-dependency.patch
                0005-rb-eventmachine-can-have-a-separate-namespace-than-r.patch
                0004-Added-EventMachineTransport-class.patch
                0003-Added-ruby-eventmachine-compatible-client-code.patch
                0002-Added-rb-eventmachine-option-to-the-compiler.patch
                0001-Ruby-client-increments-sequence-ids.patch

I've attached a patch series implementing an EventMachine client for thrift. The work is based on the Twisted and NodeJS implementations.

There is a new compiler namespace rb:eventmachine that will generate the em specific bindings.

All of the thrift calls will return an EventMachine::Deferrable object. Once the service has responded, the deferrable's .callback function will be executed with the resulting value if there is one. Here's a sample:

{code}
require 'eventmachine'
require 'gen-rb.eventmachine/example_client'
require 'thrift/transport/event_machine_transport'

EM.run do
  connection = Thrift::EventMachineTransport.connect(ExampleClient, host, port)
  connection.errback { puts "Could not connect to server"; EM.stop_event_loop; }
  connection.callback do |client|
    client.rpc_method_a(value).callback {|result| puts "got result #{result}"; }
  end
end
{code}
There is a real example in tutorial/rb/RubyClientEventMachine.rb. There are also roundtrip tests in event_machine_client_spec.rb that provide in depth examples.

Note that 'EventMachine' is a development_dependency in the gemspec instead of a runtime dependency. Since most existing projects do not use EventMachine it probably doesn't make sense to force them to install the EM gem. If you want to use this you will need to require eventmachine yourself. You will also need to require 'thrift/transport/event_machine_transport' as it references EventMachine classes so it is not required by default in thrift.rb.
 

                
> Make Thrift EventMachine Compatible
> -----------------------------------
>
>                 Key: THRIFT-146
>                 URL: https://issues.apache.org/jira/browse/THRIFT-146
>             Project: Thrift
>          Issue Type: Improvement
>          Components: Ruby - Library
>         Environment: Ruby and EventMachine
>            Reporter: Ben Taitelbaum
>            Priority: Trivial
>         Attachments: 0001-Ruby-client-increments-sequence-ids.patch, 0002-Added-rb-eventmachine-option-to-the-compiler.patch, 0003-Added-ruby-eventmachine-compatible-client-code.patch, 0004-Added-EventMachineTransport-class.patch, 0005-rb-eventmachine-can-have-a-separate-namespace-than-r.patch, 0006-Added-eventmachine-as-a-dev-dependency.patch, 0007-Generate-eventmachine-bindings-for-tests.patch, 0008-Initial-event-machine-test.patch, 0009-Added-an-asnyc-test-for-EventMachine.patch, 0010-Added-test-for-oneway-functions-with-eventmachine.patch, 0011-Added-eventmachine-test-for-void-functions.patch, 0012-Eventmachine-triggers-errback-on-connect-errors.patch, 0013-Added-timeout-option-to-eventmachine-transport.patch, 0014-Eventmachine-spec-cleanup-for-ruby-1.8.patch, 0015-Added-EventMachine-tutorial-example.patch, thrift_eventmachine.rb
>
>
> I wrote a prototype EventMachine client/server for Thrift (BinaryProtocol), and while it's not fully functional, the results are so promising, that I think it would be worth it to either include an EM client/server with the thrift distribution, or at least rework the libraries so that they can support EM without having to copy/paste all the code I did.
> I'm attaching my prototype as an example. It requires the eventmachine and statemachine gems. It's wired to support a simple echo service. It's a little confusing in that I reused the same statemachine for both client and server, doesn't handle exceptions, and has a bug where it'll handle all requests from one client before handling requests from another, but hey, it's a prototype.
> EM uses very different semantics from typical client/server, and this presents difficulty wiring it to the current thrift protocols. For example, while currently, you can call call prot.read(n) to read n bytes off of a stream, or wait until they're available, with EM, if n bytes aren't available, you simply don't handle the call yet. I handled this by trying to read as many bytes as need be, and keeping track of how much to backup in the stream, ultimately only transitioning to the next state in the statemachine if we were able to read all the bytes needed. This actually works fairly well, but it would be better if we had a byte count at each step so we could tell right away if we had enough data.
> The use of EM allows for new asynchronous semantics for thrift calls, in that the client returns right away from a call, and its callback is called when a result (or exception) is available. Backwards compatibility could still be achieved by blocking on a call, but at least in my experience, in most of the cases having callbacks would be a huge optimization. There are some cases where I do want to either ensure that calls happen sequentially, or are at least handled in the same order.
> These are the changes I believe would have to be made in order to support an EM thrift connection:
> 1. syntax to indicate that certain methods can be called asynchronously with callbacks. Since async is already a reserved keyword, and is changing to noreturn, what about using this?
> 2. I would propose moving all reading and writing to the same class. So instead of having ThriftStruct#read, we would have Protocol#read_struct. It seems out of place to me to have a model handle its own reading / writing.
> 3. support for byte counts in the protocols. It would be helpful to have a clear way to get the number of bytes that must be read to retrieve message headers, arguments, and results. Alternatively, the protocols could support read_or_backup semantics, but as you can see in my prototype, this can get messy.
> Please let me know what you think about this proposal, and the possibility of using EventMachine.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira