protobuf 1.1.0.beta1 → 1.1.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/Rakefile +4 -0
- data/lib/protobuf/rpc/connectors/base.rb +2 -2
- data/lib/protobuf/rpc/connectors/eventmachine.rb +19 -7
- data/lib/protobuf/rpc/connectors/socket.rb +0 -1
- data/lib/protobuf/rpc/servers/evented_server.rb +0 -1
- data/lib/protobuf/rpc/servers/socket_runner.rb +12 -1
- data/lib/protobuf/rpc/servers/socket_server.rb +73 -72
- data/lib/protobuf/rpc/service.rb +2 -2
- data/lib/protobuf/version.rb +1 -1
- data/spec/benchmark/tasks.rb +126 -0
- data/spec/helper/server.rb +13 -10
- data/spec/spec_helper.rb +3 -3
- data/spec/unit/rpc/client_spec.rb +55 -22
- data/spec/unit/rpc/servers/socket_server_spec.rb +0 -1
- metadata +20 -18
    
        data/Gemfile
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/Rakefile
    CHANGED
    
    
| @@ -11,8 +11,8 @@ module Protobuf | |
| 11 11 | 
             
                  DEFAULT_OPTIONS = {
         | 
| 12 12 | 
             
                    :service        => nil,           # Service to invoke
         | 
| 13 13 | 
             
                    :method         => nil,           # Service method to call
         | 
| 14 | 
            -
                    :host           => ' | 
| 15 | 
            -
                    :port           => ' | 
| 14 | 
            +
                    :host           => '127.0.0.1',   # A default host (usually overridden)
         | 
| 15 | 
            +
                    :port           => '9399',        # A default port (usually overridden)
         | 
| 16 16 | 
             
                    :request        => nil,           # The request object sent by the client
         | 
| 17 17 | 
             
                    :request_type   => nil,           # The request type expected by the client
         | 
| 18 18 | 
             
                    :response_type  => nil,           # The response type expected by the client
         | 
| @@ -5,12 +5,12 @@ module Protobuf | |
| 5 5 | 
             
              module Rpc
         | 
| 6 6 | 
             
                module Connectors
         | 
| 7 7 | 
             
                  class EventMachine < Base
         | 
| 8 | 
            -
             | 
| 8 | 
            +
             | 
| 9 9 | 
             
                    def send_request
         | 
| 10 10 | 
             
                      ensure_em_running do 
         | 
| 11 11 | 
             
                        f = Fiber.current
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                        EM. | 
| 12 | 
            +
             | 
| 13 | 
            +
                        EM.next_tick do
         | 
| 14 14 | 
             
                          log_debug "[#{log_signature}] Scheduling EventMachine client request to be created on next tick"
         | 
| 15 15 | 
             
                          cnxn = EMClient.connect(options, &ensure_cb)
         | 
| 16 16 | 
             
                          cnxn.on_success(&success_cb) if success_cb
         | 
| @@ -22,7 +22,7 @@ module Protobuf | |
| 22 22 | 
             
                        async? ? true : set_timeout_and_validate_fiber
         | 
| 23 23 | 
             
                      end
         | 
| 24 24 | 
             
                    end
         | 
| 25 | 
            -
             | 
| 25 | 
            +
             | 
| 26 26 | 
             
                    # Returns a callable that ensures any errors will be returned to the client
         | 
| 27 27 | 
             
                    # 
         | 
| 28 28 | 
             
                    # If a failure callback was set, just use that as a direct assignment
         | 
| @@ -36,11 +36,20 @@ module Protobuf | |
| 36 36 | 
             
                    def log_signature
         | 
| 37 37 | 
             
                      @log_signature ||= "client-#{self.class}"
         | 
| 38 38 | 
             
                    end
         | 
| 39 | 
            -
             | 
| 39 | 
            +
             | 
| 40 40 | 
             
                    private
         | 
| 41 41 |  | 
| 42 42 | 
             
                    def ensure_em_running(&blk)
         | 
| 43 | 
            -
                      EM.reactor_running?  | 
| 43 | 
            +
                      if EM.reactor_running? 
         | 
| 44 | 
            +
                        @global_reactor = true
         | 
| 45 | 
            +
                        yield
         | 
| 46 | 
            +
                      else 
         | 
| 47 | 
            +
                        @global_reactor = false
         | 
| 48 | 
            +
                        EM.fiber_run do 
         | 
| 49 | 
            +
                          blk.call
         | 
| 50 | 
            +
                          EM.stop
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                      end
         | 
| 44 53 | 
             
                    end
         | 
| 45 54 |  | 
| 46 55 | 
             
                    def resume_fiber(fib)
         | 
| @@ -54,6 +63,7 @@ module Protobuf | |
| 54 63 | 
             
                      message = 'Synchronous client failed: %s' % ex.message
         | 
| 55 64 | 
             
                      err = Protobuf::Rpc::ClientError.new(Protobuf::Socketrpc::ErrorReason::RPC_ERROR, message)
         | 
| 56 65 | 
             
                      ensure_cb.call(err)
         | 
| 66 | 
            +
                      EM.stop if !@global_reactor
         | 
| 57 67 | 
             
                    end
         | 
| 58 68 |  | 
| 59 69 | 
             
                    def set_timeout_and_validate_fiber
         | 
| @@ -61,6 +71,7 @@ module Protobuf | |
| 61 71 | 
             
                        message = 'Client timeout of %d seconds expired' % @options[:timeout]
         | 
| 62 72 | 
             
                        err = Protobuf::Rpc::ClientError.new(Protobuf::Socketrpc::ErrorReason::RPC_ERROR, message)
         | 
| 63 73 | 
             
                        ensure_cb.call(err)
         | 
| 74 | 
            +
                        EM.stop if !@global_reactor
         | 
| 64 75 | 
             
                      end
         | 
| 65 76 |  | 
| 66 77 | 
             
                      Fiber.yield
         | 
| @@ -68,7 +79,8 @@ module Protobuf | |
| 68 79 | 
             
                      message = "Synchronous calls must be in 'EM.fiber_run' block" 
         | 
| 69 80 | 
             
                      err = Protobuf::Rpc::ClientError.new(Protobuf::Socketrpc::ErrorReason::RPC_ERROR, message)
         | 
| 70 81 | 
             
                      ensure_cb.call(err)
         | 
| 71 | 
            -
             | 
| 82 | 
            +
                      EM.stop if !@global_reactor
         | 
| 83 | 
            +
                   end
         | 
| 72 84 |  | 
| 73 85 | 
             
                  end
         | 
| 74 86 | 
             
                end
         | 
| @@ -9,7 +9,6 @@ module Protobuf | |
| 9 9 | 
             
                  # Initialize a new read buffer for storing client request info
         | 
| 10 10 | 
             
                  def post_init
         | 
| 11 11 | 
             
                    log_debug '[server] Post init, new read buffer created'
         | 
| 12 | 
            -
                    
         | 
| 13 12 | 
             
                    @stats = Protobuf::Rpc::Stat.new(:SERVER, true)
         | 
| 14 13 | 
             
                    @stats.client = Socket.unpack_sockaddr_in(get_peername)
         | 
| 15 14 |  | 
| @@ -9,7 +9,18 @@ module Protobuf | |
| 9 9 |  | 
| 10 10 | 
             
                  def self.run(server)
         | 
| 11 11 | 
             
                    Protobuf::Logger.info "SocketServer Running"
         | 
| 12 | 
            -
                     | 
| 12 | 
            +
                    server_config = case 
         | 
| 13 | 
            +
                                    when server.is_a?(OpenStruct) then 
         | 
| 14 | 
            +
                                      server.marshal_dump
         | 
| 15 | 
            +
                                    when server.is_a?(Hash) then
         | 
| 16 | 
            +
                                      server
         | 
| 17 | 
            +
                                    when server.respond_to?(:to_hash) then
         | 
| 18 | 
            +
                                      server.to_hash
         | 
| 19 | 
            +
                                    else
         | 
| 20 | 
            +
                                      raise "Cannot parser Socket Server - server options"
         | 
| 21 | 
            +
                                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    Protobuf::Rpc::SocketServer.run(server_config)
         | 
| 13 24 | 
             
                  end
         | 
| 14 25 | 
             
                end
         | 
| 15 26 |  | 
| @@ -6,96 +6,97 @@ module Protobuf | |
| 6 6 | 
             
                  include Protobuf::Rpc::Server
         | 
| 7 7 | 
             
                  include Protobuf::Logger::LogMethods
         | 
| 8 8 |  | 
| 9 | 
            -
                  class << self
         | 
| 10 9 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 10 | 
            +
                  def self.cleanup? 
         | 
| 11 | 
            +
                    # every 10 connections run a cleanup routine after closing the response
         | 
| 12 | 
            +
                    @threads.size > (@thread_threshold - 1) && (@threads.size % @thread_threshold) == 0
         | 
| 13 | 
            +
                  end
         | 
| 15 14 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 15 | 
            +
                  def self.cleanup_threads
         | 
| 16 | 
            +
                    log_debug "[#{log_signature}] Thread cleanup - #{@threads.size} - start"
         | 
| 18 17 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                        end
         | 
| 18 | 
            +
                    @threads = @threads.select do |t| 
         | 
| 19 | 
            +
                      if t[:thread].alive? 
         | 
| 20 | 
            +
                        true  
         | 
| 21 | 
            +
                      else
         | 
| 22 | 
            +
                        t[:thread].join
         | 
| 23 | 
            +
                        @working.delete(t[:socket])
         | 
| 24 | 
            +
                        false
         | 
| 27 25 | 
             
                      end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                      log_debug "[#{log_signature}] Thread cleanup - #{@threads.size} - complete"
         | 
| 30 26 | 
             
                    end
         | 
| 31 27 |  | 
| 32 | 
            -
                     | 
| 33 | 
            -
             | 
| 34 | 
            -
                    end
         | 
| 28 | 
            +
                    log_debug "[#{log_signature}] Thread cleanup - #{@threads.size} - complete"
         | 
| 29 | 
            +
                  end
         | 
| 35 30 |  | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 31 | 
            +
                  def self.log_signature
         | 
| 32 | 
            +
                    @log_signature ||= "server-#{self}"
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def self.new_worker(socket)
         | 
| 36 | 
            +
                    Thread.new(socket) do |sock|
         | 
| 37 | 
            +
                      Protobuf::Rpc::SocketServer::Worker.new(sock) do |s|
         | 
| 38 | 
            +
                        s.close
         | 
| 41 39 | 
             
                      end
         | 
| 42 40 | 
             
                    end
         | 
| 41 | 
            +
                  end
         | 
| 43 42 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
                     | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
                             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
                               | 
| 43 | 
            +
                  def self.run(opts = {})
         | 
| 44 | 
            +
                    log_debug "[#{log_signature}] Run"
         | 
| 45 | 
            +
                    host = opts.fetch(:host, "127.0.0.1")
         | 
| 46 | 
            +
                    port = opts.fetch(:port, 9399)
         | 
| 47 | 
            +
                    backlog = opts.fetch(:backlog, 100)
         | 
| 48 | 
            +
                    thread_threshold = opts.fetch(:thread_threshold, 100)
         | 
| 49 | 
            +
                    auto_collect_timeout = opts.fetch(:auto_collect_timeout, 20)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    @running = true
         | 
| 52 | 
            +
                    @threads = []
         | 
| 53 | 
            +
                    @thread_threshold = thread_threshold
         | 
| 54 | 
            +
                    @server = TCPServer.new(host, port)
         | 
| 55 | 
            +
                    @server.listen(backlog)
         | 
| 56 | 
            +
                    @working = []
         | 
| 57 | 
            +
                    @listen_fds = [@server]
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    while running?
         | 
| 60 | 
            +
                      log_debug "[#{log_signature}] Waiting for connections"
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                      if ready_cnxns = IO.select(@listen_fds, [], [], auto_collect_timeout)
         | 
| 63 | 
            +
                        cnxns = ready_cnxns.first
         | 
| 64 | 
            +
                        cnxns.each do |client|
         | 
| 65 | 
            +
                          case 
         | 
| 66 | 
            +
                          when !running? then
         | 
| 67 | 
            +
                            # no-op
         | 
| 68 | 
            +
                          when client == @server then 
         | 
| 69 | 
            +
                            log_debug "[#{log_signature}] Accepted new connection"
         | 
| 70 | 
            +
                            client, sockaddr = @server.accept
         | 
| 71 | 
            +
                            @listen_fds << client
         | 
| 72 | 
            +
                          else 
         | 
| 73 | 
            +
                            if !@working.include?(client)
         | 
| 74 | 
            +
                              @working << @listen_fds.delete(client)
         | 
| 75 | 
            +
                              log_debug "[#{log_signature}] Working" 
         | 
| 76 | 
            +
                              @threads << { :thread => new_worker(client), :socket => client }
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                              cleanup_threads if cleanup?
         | 
| 77 79 | 
             
                            end
         | 
| 78 80 | 
             
                          end
         | 
| 79 | 
            -
                        else
         | 
| 80 | 
            -
                          # Run a cleanup if select times out while waiting
         | 
| 81 | 
            -
                          cleanup_threads if @threads.size > 1
         | 
| 82 81 | 
             
                        end
         | 
| 82 | 
            +
                      else
         | 
| 83 | 
            +
                        # Run a cleanup if select times out while waiting
         | 
| 84 | 
            +
                        cleanup_threads if @threads.size > 1
         | 
| 83 85 | 
             
                      end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                    rescue 
         | 
| 86 | 
            -
                      # Closing the server causes the loop to raise an exception here
         | 
| 87 | 
            -
                      raise if running?
         | 
| 88 86 | 
             
                    end
         | 
| 89 87 |  | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
                     | 
| 88 | 
            +
                  rescue 
         | 
| 89 | 
            +
                    # Closing the server causes the loop to raise an exception here
         | 
| 90 | 
            +
                    raise if running?
         | 
| 91 | 
            +
                  end
         | 
| 93 92 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
                    end
         | 
| 93 | 
            +
                  def self.running?
         | 
| 94 | 
            +
                    @running
         | 
| 95 | 
            +
                  end
         | 
| 98 96 |  | 
| 97 | 
            +
                  def self.stop 
         | 
| 98 | 
            +
                    @running = false
         | 
| 99 | 
            +
                    @server.close if @server
         | 
| 99 100 | 
             
                  end
         | 
| 100 101 |  | 
| 101 102 | 
             
                  class Worker 
         | 
    
        data/lib/protobuf/rpc/service.rb
    CHANGED
    
    
    
        data/lib/protobuf/version.rb
    CHANGED
    
    
| @@ -0,0 +1,126 @@ | |
| 1 | 
            +
            require 'benchmark'
         | 
| 2 | 
            +
            require 'helper/all'
         | 
| 3 | 
            +
            require 'proto/test_service_impl'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            namespace :benchmark do
         | 
| 6 | 
            +
              include SilentConstants
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def benchmark_wrapper(global_bench = nil)
         | 
| 9 | 
            +
                if global_bench
         | 
| 10 | 
            +
                  yield global_bench
         | 
| 11 | 
            +
                else
         | 
| 12 | 
            +
                  Benchmark.bm(10) do |bench|
         | 
| 13 | 
            +
                    yield bench
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def em_client_em_server(number_tests, test_length, global_bench = nil)
         | 
| 19 | 
            +
                EM.stop if EM.reactor_running?
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                EventMachine.fiber_run do 
         | 
| 22 | 
            +
                  StubServer.new do |server|
         | 
| 23 | 
            +
                    client = Spec::Proto::TestService.client(:async => false)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    benchmark_wrapper(global_bench) do |bench|
         | 
| 26 | 
            +
                      bench.report("ES / EC") do 
         | 
| 27 | 
            +
                        (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  EM.stop
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def em_client_sock_server(number_tests, test_length, global_bench = nil)
         | 
| 37 | 
            +
                EM.stop if EM.reactor_running?
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                EventMachine.fiber_run do
         | 
| 40 | 
            +
                  StubServer.new(:server => Protobuf::Rpc::SocketServer, :port => 9399) do |server| 
         | 
| 41 | 
            +
                    client = Spec::Proto::TestService.client(:async => false, :port => 9399)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    benchmark_wrapper(global_bench) do |bench|
         | 
| 44 | 
            +
                      bench.report("SS / EC") do 
         | 
| 45 | 
            +
                        (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  EM.stop
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def sock_client_sock_server(number_tests, test_length, global_bench = nil)
         | 
| 55 | 
            +
                EM.stop if EM.reactor_running?
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                StubServer.new(:server => Protobuf::Rpc::SocketServer, :port => 9399) do |server| 
         | 
| 58 | 
            +
                  with_constants "Protobuf::ConnectorType" => "Socket" do
         | 
| 59 | 
            +
                    client = Spec::Proto::TestService.client(:async => false, :port => 9399)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    benchmark_wrapper(global_bench) do |bench|
         | 
| 62 | 
            +
                      bench.report("SS / SC") do 
         | 
| 63 | 
            +
                        (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              def sock_client_em_server(number_tests, test_length, global_bench = nil)
         | 
| 71 | 
            +
                EM.stop if EM.reactor_running?
         | 
| 72 | 
            +
                em_thread = Thread.new { EM.run }
         | 
| 73 | 
            +
                Thread.pass until EM.reactor_running?
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                StubServer.new(:port => 9399) do |server| 
         | 
| 76 | 
            +
                  with_constants "Protobuf::ConnectorType" => "Socket" do
         | 
| 77 | 
            +
                    client = Spec::Proto::TestService.client(:async => false, :port => 9399)
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    benchmark_wrapper(global_bench) do |bench|
         | 
| 80 | 
            +
                      bench.report("ES / SC") do 
         | 
| 81 | 
            +
                        (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                EM.stop
         | 
| 88 | 
            +
                Thread.kill(em_thread) if em_thread
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              desc "benchmark EventMachine client with EventMachine server"
         | 
| 92 | 
            +
              task :em_client_em_server, [:number, :length] do |t, args|
         | 
| 93 | 
            +
                args.with_defaults(:number => 1000, :length => 100)
         | 
| 94 | 
            +
                em_client_em_server(args[:number], args[:length])
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              desc "benchmark EventMachine client with Socket server"
         | 
| 98 | 
            +
              task :em_client_sock_server, [:number, :length] do |t, args|
         | 
| 99 | 
            +
                args.with_defaults(:number => 1000, :length => 100)
         | 
| 100 | 
            +
                em_client_sock_server(args[:number], args[:length])
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              desc "benchmark Socket client with Socket server"
         | 
| 104 | 
            +
              task :sock_client_sock_server, [:number, :length] do |t, args|
         | 
| 105 | 
            +
                args.with_defaults(:number => 1000, :length => 100)
         | 
| 106 | 
            +
                sock_client_sock_server(args[:number], args[:length])
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              desc "benchmark Socket client with EventMachine server"
         | 
| 110 | 
            +
              task :sock_client_em_server, [:number, :length] do |t, args|
         | 
| 111 | 
            +
                args.with_defaults(:number => 1000, :length => 100)
         | 
| 112 | 
            +
                sock_client_em_server(args[:number], args[:length])
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              desc "benchmark server performance"
         | 
| 116 | 
            +
              task :servers, [:number, :length] do |t, args|
         | 
| 117 | 
            +
                args.with_defaults(:number => 1000, :length => 100)
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                Benchmark.bm(10) do |bench|
         | 
| 120 | 
            +
                  em_client_em_server(args[:number], args[:length], bench)
         | 
| 121 | 
            +
                  em_client_sock_server(args[:number], args[:length], bench)
         | 
| 122 | 
            +
                  sock_client_sock_server(args[:number], args[:length], bench)
         | 
| 123 | 
            +
                  sock_client_em_server(args[:number], args[:length], bench)
         | 
| 124 | 
            +
                end
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
            end
         | 
    
        data/spec/helper/server.rb
    CHANGED
    
    | @@ -1,19 +1,19 @@ | |
| 1 1 | 
             
            require 'ostruct'
         | 
| 2 2 | 
             
            require 'protobuf/common/logger'
         | 
| 3 3 | 
             
            require 'protobuf/rpc/server'
         | 
| 4 | 
            +
            require 'protobuf/rpc/servers/socket_server'
         | 
| 5 | 
            +
            require 'protobuf/rpc/servers/socket_runner'
         | 
| 4 6 | 
             
            require 'spec/proto/test_service_impl'
         | 
| 5 7 |  | 
| 6 8 | 
             
            module StubProtobufServerFactory
         | 
| 7 9 | 
             
              def self.build(delay)
         | 
| 8 10 | 
             
                new_server = Class.new(Protobuf::Rpc::EventedServer) do
         | 
| 9 | 
            -
                   | 
| 10 | 
            -
                     | 
| 11 | 
            -
             | 
| 12 | 
            -
                    end
         | 
| 11 | 
            +
                  def self.sleep_interval
         | 
| 12 | 
            +
                    @sleep_interval
         | 
| 13 | 
            +
                  end
         | 
| 13 14 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                    end
         | 
| 15 | 
            +
                  def self.sleep_interval=(si)
         | 
| 16 | 
            +
                    @sleep_interval = si
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 19 | 
             
                  def post_init
         | 
| @@ -36,7 +36,7 @@ class StubServer | |
| 36 36 | 
             
                @running = true
         | 
| 37 37 | 
             
                @options = OpenStruct.new({
         | 
| 38 38 | 
             
                    :host => "127.0.0.1", 
         | 
| 39 | 
            -
                    :port =>  | 
| 39 | 
            +
                    :port => 9399, 
         | 
| 40 40 | 
             
                    :delay => 0, 
         | 
| 41 41 | 
             
                    :server => Protobuf::Rpc::EventedServer
         | 
| 42 42 | 
             
                  }.merge(opts))
         | 
| @@ -51,7 +51,9 @@ class StubServer | |
| 51 51 | 
             
                if @options.server == Protobuf::Rpc::EventedServer
         | 
| 52 52 | 
             
                  start_em_server
         | 
| 53 53 | 
             
                else
         | 
| 54 | 
            -
                  Protobuf::Rpc::SocketRunner.run( | 
| 54 | 
            +
                  @sock_server = Thread.new(@options) { |opt| Protobuf::Rpc::SocketRunner.run(opt) }
         | 
| 55 | 
            +
                  @sock_server.abort_on_exception = true # Set for testing purposes
         | 
| 56 | 
            +
                  Thread.pass until Protobuf::Rpc::SocketServer.running?
         | 
| 55 57 | 
             
                end
         | 
| 56 58 | 
             
                log_debug "[stub-server] Server started #{@options.host}:#{@options.port}"
         | 
| 57 59 | 
             
              rescue => ex
         | 
| @@ -67,9 +69,10 @@ class StubServer | |
| 67 69 |  | 
| 68 70 | 
             
              def stop
         | 
| 69 71 | 
             
                if @options.server == Protobuf::Rpc::EventedServer
         | 
| 70 | 
            -
                  EventMachine.stop_server(@server_handle)
         | 
| 72 | 
            +
                  EventMachine.stop_server(@server_handle) if @server_handle
         | 
| 71 73 | 
             
                else
         | 
| 72 74 | 
             
                  Protobuf::Rpc::SocketRunner.stop
         | 
| 75 | 
            +
                  Thread.kill(@sock_server) if @sock_server
         | 
| 73 76 | 
             
                end
         | 
| 74 77 | 
             
                @running = false
         | 
| 75 78 | 
             
              end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -26,9 +26,9 @@ end | |
| 26 26 |  | 
| 27 27 | 
             
            class ::Protobuf::Rpc::Client
         | 
| 28 28 | 
             
              def == other
         | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 29 | 
            +
                connector.options == other.options && \
         | 
| 30 | 
            +
                  success_cb == other.success_cb && \
         | 
| 31 | 
            +
                  failure_cb == other.failure_cb
         | 
| 32 32 | 
             
              end
         | 
| 33 33 | 
             
            end
         | 
| 34 34 |  | 
| @@ -9,7 +9,7 @@ describe Protobuf::Rpc::Client do | |
| 9 9 | 
             
                    StubServer.new(:delay => 3) do |server|
         | 
| 10 10 | 
             
                      client = Spec::Proto::TestService.client(:async => false)
         | 
| 11 11 | 
             
                      start = now
         | 
| 12 | 
            -
             | 
| 12 | 
            +
             | 
| 13 13 | 
             
                      client.find(:name => "Test Name", :active => true) do |c|
         | 
| 14 14 | 
             
                        c.on_success do |succ|
         | 
| 15 15 | 
             
                          succ.name.should eq("Test Name")
         | 
| @@ -68,40 +68,73 @@ describe Protobuf::Rpc::Client do | |
| 68 68 | 
             
                  subject.should raise_error(RuntimeError, /timeout/i)
         | 
| 69 69 | 
             
                end
         | 
| 70 70 |  | 
| 71 | 
            +
                context "without reactor_running?" do 
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  it "throws a timeout when client timeout is exceeded" do
         | 
| 74 | 
            +
                    subject = Proc.new do
         | 
| 75 | 
            +
                      StubServer.new(:delay => 2) do |server|
         | 
| 76 | 
            +
                        client = Spec::Proto::TestService.client(:async => false, :timeout => 1)
         | 
| 77 | 
            +
                        client.find(:name => "Test Name", :active => true)
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    subject.should raise_error(RuntimeError, /timeout/i)
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  it "calls failure_cb & throws a timeout when client timeout is exceeded" do
         | 
| 85 | 
            +
                    failure_message = nil
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    subject = Proc.new do
         | 
| 88 | 
            +
                      StubServer.new(:delay => 2) do |server|
         | 
| 89 | 
            +
                        client = Spec::Proto::TestService.client(:async => false, :timeout => 1)
         | 
| 90 | 
            +
                        client.find(:name => "Test Name", :active => true) do |c|
         | 
| 91 | 
            +
                          c.on_failure do |f|
         | 
| 92 | 
            +
                            failure_message = f.message
         | 
| 93 | 
            +
                          end
         | 
| 94 | 
            +
                        end
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    subject.call
         | 
| 99 | 
            +
                    failure_message.should match(/timeout/)
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 71 104 | 
             
              end
         | 
| 72 | 
            -
             | 
| 105 | 
            +
             | 
| 73 106 | 
             
              context 'when creating a client from a service' do
         | 
| 74 | 
            -
             | 
| 107 | 
            +
             | 
| 75 108 | 
             
                it 'should be able to get a client through the Service#client helper method' do
         | 
| 76 109 | 
             
                  Spec::Proto::TestService.client(:port => 9191).should eq(Protobuf::Rpc::Client.new(:service => Spec::Proto::TestService, :port => 9191))
         | 
| 77 110 | 
             
                end
         | 
| 78 | 
            -
             | 
| 111 | 
            +
             | 
| 79 112 | 
             
                it "should be able to override a service location's host and port" do
         | 
| 80 113 | 
             
                  Spec::Proto::TestService.located_at 'somewheregreat.com:12345'
         | 
| 81 114 | 
             
                  clean_client = Spec::Proto::TestService.client
         | 
| 82 115 | 
             
                  clean_client.options[:host].should eq('somewheregreat.com')
         | 
| 83 116 | 
             
                  clean_client.options[:port].should eq(12345)
         | 
| 84 | 
            -
             | 
| 117 | 
            +
             | 
| 85 118 | 
             
                  updated_client = Spec::Proto::TestService.client(:host => 'amazing.com', :port => 54321)
         | 
| 86 119 | 
             
                  updated_client.options[:host].should eq('amazing.com')
         | 
| 87 120 | 
             
                  updated_client.options[:port].should eq(54321)
         | 
| 88 121 | 
             
                end
         | 
| 89 | 
            -
             | 
| 122 | 
            +
             | 
| 90 123 | 
             
                it 'should be able to define the syncronicity of the client request' do
         | 
| 91 124 | 
             
                  client = Spec::Proto::TestService.client(:async => false)
         | 
| 92 125 | 
             
                  client.options[:async].should be_false
         | 
| 93 126 | 
             
                  client.async?.should be_false
         | 
| 94 | 
            -
             | 
| 127 | 
            +
             | 
| 95 128 | 
             
                  client = Spec::Proto::TestService.client(:async => true)
         | 
| 96 129 | 
             
                  client.options[:async].should be_true
         | 
| 97 130 | 
             
                  client.async?.should be_true
         | 
| 98 131 | 
             
                end
         | 
| 99 | 
            -
             | 
| 132 | 
            +
             | 
| 100 133 | 
             
                it 'should be able to define which service to create itself for' do
         | 
| 101 134 | 
             
                  client = Protobuf::Rpc::Client.new :service => Spec::Proto::TestService
         | 
| 102 135 | 
             
                  client.options[:service].should eq(Spec::Proto::TestService)
         | 
| 103 136 | 
             
                end
         | 
| 104 | 
            -
             | 
| 137 | 
            +
             | 
| 105 138 | 
             
                it 'should have a hard default for host and port on a service that has not been configured' do
         | 
| 106 139 | 
             
                  reset_service_location Spec::Proto::TestService
         | 
| 107 140 | 
             
                  client = Spec::Proto::TestService.client
         | 
| @@ -110,33 +143,33 @@ describe Protobuf::Rpc::Client do | |
| 110 143 | 
             
                end
         | 
| 111 144 |  | 
| 112 145 | 
             
              end
         | 
| 113 | 
            -
             | 
| 146 | 
            +
             | 
| 114 147 | 
             
              context 'when calling methods on a service client' do
         | 
| 115 | 
            -
             | 
| 148 | 
            +
             | 
| 116 149 | 
             
                # NOTE: we are assuming the service methods are accurately 
         | 
| 117 150 | 
             
                # defined inside spec/proto/test_service.rb,
         | 
| 118 151 | 
             
                # namely the :find method
         | 
| 119 | 
            -
             | 
| 152 | 
            +
             | 
| 120 153 | 
             
                it 'should respond to defined service methods' do
         | 
| 121 154 | 
             
                  client = Spec::Proto::TestService.client
         | 
| 122 155 | 
             
                  client.should_receive(:send_request).and_return(nil)
         | 
| 123 156 | 
             
                  expect { client.find(nil) }.should_not raise_error
         | 
| 124 157 | 
             
                end
         | 
| 125 | 
            -
             | 
| 158 | 
            +
             | 
| 126 159 | 
             
                it 'raises a NameError when accessing a var that does not exist' do
         | 
| 127 160 | 
             
                  pending
         | 
| 128 161 | 
             
                end
         | 
| 129 | 
            -
             | 
| 162 | 
            +
             | 
| 130 163 | 
             
                it 'should be able to set and get local variables within client response blocks' do
         | 
| 131 164 | 
             
                  outer_value = 'OUTER'
         | 
| 132 165 | 
             
                  inner_value = 'INNER'
         | 
| 133 166 | 
             
                  client = Spec::Proto::TestService.client(:async => true)
         | 
| 134 | 
            -
             | 
| 167 | 
            +
             | 
| 135 168 | 
             
                  EM.should_receive(:reactor_running?).and_return(true)
         | 
| 136 | 
            -
                  EM.stub!(: | 
| 169 | 
            +
                  EM.stub!(:next_tick) do
         | 
| 137 170 | 
             
                    client.success_cb.call(inner_value)
         | 
| 138 171 | 
             
                  end
         | 
| 139 | 
            -
             | 
| 172 | 
            +
             | 
| 140 173 | 
             
                  client.find(nil) do |c|
         | 
| 141 174 | 
             
                    c.on_success do |response|
         | 
| 142 175 | 
             
                      outer_value.should eq('OUTER')
         | 
| @@ -145,11 +178,11 @@ describe Protobuf::Rpc::Client do | |
| 145 178 | 
             
                  end
         | 
| 146 179 | 
             
                  outer_value.should eq(inner_value)
         | 
| 147 180 | 
             
                end
         | 
| 148 | 
            -
             | 
| 181 | 
            +
             | 
| 149 182 | 
             
              end
         | 
| 150 | 
            -
             | 
| 183 | 
            +
             | 
| 151 184 | 
             
              context 'when receiving request objects' do
         | 
| 152 | 
            -
             | 
| 185 | 
            +
             | 
| 153 186 | 
             
                it 'should be able to create the correct request object if passed a hash' do
         | 
| 154 187 | 
             
                  client = Spec::Proto::TestService.client
         | 
| 155 188 | 
             
                  client.should_receive(:send_request)
         | 
| @@ -158,7 +191,7 @@ describe Protobuf::Rpc::Client do | |
| 158 191 | 
             
                  client.options[:request].name.should eq('Test Name')
         | 
| 159 192 | 
             
                  client.options[:request].active.should eq(false)
         | 
| 160 193 | 
             
                end
         | 
| 161 | 
            -
             | 
| 194 | 
            +
             | 
| 162 195 | 
             
              end
         | 
| 163 | 
            -
             | 
| 196 | 
            +
             | 
| 164 197 | 
             
            end
         | 
| @@ -34,7 +34,6 @@ describe Protobuf::Rpc::SocketServer do | |
| 34 34 | 
             
              end
         | 
| 35 35 |  | 
| 36 36 | 
             
              context "Eventmachine client" do 
         | 
| 37 | 
            -
             | 
| 38 37 | 
             
                it "calls the service in the client request" do 
         | 
| 39 38 | 
             
                  with_constants "Protobuf::ConnectorType" => "Evented" do
         | 
| 40 39 | 
             
                    client = Spec::Proto::TestService.client(:async => false, :port => 9399, :host => "127.0.0.1")
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: protobuf
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.1.0. | 
| 4 | 
            +
              version: 1.1.0.beta2
         | 
| 5 5 | 
             
              prerelease: 6
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -10,11 +10,11 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2012-01- | 
| 13 | 
            +
            date: 2012-01-30 00:00:00.000000000Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: eventmachine
         | 
| 17 | 
            -
              requirement: & | 
| 17 | 
            +
              requirement: &2152749580 !ruby/object:Gem::Requirement
         | 
| 18 18 | 
             
                none: false
         | 
| 19 19 | 
             
                requirements:
         | 
| 20 20 | 
             
                - - ~>
         | 
| @@ -22,10 +22,10 @@ dependencies: | |
| 22 22 | 
             
                    version: 0.12.10
         | 
| 23 23 | 
             
              type: :runtime
         | 
| 24 24 | 
             
              prerelease: false
         | 
| 25 | 
            -
              version_requirements: * | 
| 25 | 
            +
              version_requirements: *2152749580
         | 
| 26 26 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 27 27 | 
             
              name: eventually
         | 
| 28 | 
            -
              requirement: & | 
| 28 | 
            +
              requirement: &2152748440 !ruby/object:Gem::Requirement
         | 
| 29 29 | 
             
                none: false
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 31 | 
             
                - - ~>
         | 
| @@ -33,10 +33,10 @@ dependencies: | |
| 33 33 | 
             
                    version: 0.1.0
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              prerelease: false
         | 
| 36 | 
            -
              version_requirements: * | 
| 36 | 
            +
              version_requirements: *2152748440
         | 
| 37 37 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 38 38 | 
             
              name: json_pure
         | 
| 39 | 
            -
              requirement: & | 
| 39 | 
            +
              requirement: &2152747240 !ruby/object:Gem::Requirement
         | 
| 40 40 | 
             
                none: false
         | 
| 41 41 | 
             
                requirements:
         | 
| 42 42 | 
             
                - - ~>
         | 
| @@ -44,10 +44,10 @@ dependencies: | |
| 44 44 | 
             
                    version: 1.6.4
         | 
| 45 45 | 
             
              type: :runtime
         | 
| 46 46 | 
             
              prerelease: false
         | 
| 47 | 
            -
              version_requirements: * | 
| 47 | 
            +
              version_requirements: *2152747240
         | 
| 48 48 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 49 49 | 
             
              name: rake
         | 
| 50 | 
            -
              requirement: & | 
| 50 | 
            +
              requirement: &2152745900 !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                none: false
         | 
| 52 52 | 
             
                requirements:
         | 
| 53 53 | 
             
                - - ~>
         | 
| @@ -55,10 +55,10 @@ dependencies: | |
| 55 55 | 
             
                    version: 0.8.7
         | 
| 56 56 | 
             
              type: :development
         | 
| 57 57 | 
             
              prerelease: false
         | 
| 58 | 
            -
              version_requirements: * | 
| 58 | 
            +
              version_requirements: *2152745900
         | 
| 59 59 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 60 60 | 
             
              name: rspec
         | 
| 61 | 
            -
              requirement: & | 
| 61 | 
            +
              requirement: &2152744960 !ruby/object:Gem::Requirement
         | 
| 62 62 | 
             
                none: false
         | 
| 63 63 | 
             
                requirements:
         | 
| 64 64 | 
             
                - - ~>
         | 
| @@ -66,10 +66,10 @@ dependencies: | |
| 66 66 | 
             
                    version: 2.8.0
         | 
| 67 67 | 
             
              type: :development
         | 
| 68 68 | 
             
              prerelease: false
         | 
| 69 | 
            -
              version_requirements: * | 
| 69 | 
            +
              version_requirements: *2152744960
         | 
| 70 70 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 71 71 | 
             
              name: yard
         | 
| 72 | 
            -
              requirement: & | 
| 72 | 
            +
              requirement: &2152743380 !ruby/object:Gem::Requirement
         | 
| 73 73 | 
             
                none: false
         | 
| 74 74 | 
             
                requirements:
         | 
| 75 75 | 
             
                - - ~>
         | 
| @@ -77,10 +77,10 @@ dependencies: | |
| 77 77 | 
             
                    version: 0.7.4
         | 
| 78 78 | 
             
              type: :development
         | 
| 79 79 | 
             
              prerelease: false
         | 
| 80 | 
            -
              version_requirements: * | 
| 80 | 
            +
              version_requirements: *2152743380
         | 
| 81 81 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 82 82 | 
             
              name: redcarpet
         | 
| 83 | 
            -
              requirement: & | 
| 83 | 
            +
              requirement: &2152737180 !ruby/object:Gem::Requirement
         | 
| 84 84 | 
             
                none: false
         | 
| 85 85 | 
             
                requirements:
         | 
| 86 86 | 
             
                - - ~>
         | 
| @@ -88,10 +88,10 @@ dependencies: | |
| 88 88 | 
             
                    version: 1.17.2
         | 
| 89 89 | 
             
              type: :development
         | 
| 90 90 | 
             
              prerelease: false
         | 
| 91 | 
            -
              version_requirements: * | 
| 91 | 
            +
              version_requirements: *2152737180
         | 
| 92 92 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 93 93 | 
             
              name: simplecov
         | 
| 94 | 
            -
              requirement: & | 
| 94 | 
            +
              requirement: &2152736600 !ruby/object:Gem::Requirement
         | 
| 95 95 | 
             
                none: false
         | 
| 96 96 | 
             
                requirements:
         | 
| 97 97 | 
             
                - - ~>
         | 
| @@ -99,7 +99,7 @@ dependencies: | |
| 99 99 | 
             
                    version: 0.5.4
         | 
| 100 100 | 
             
              type: :development
         | 
| 101 101 | 
             
              prerelease: false
         | 
| 102 | 
            -
              version_requirements: * | 
| 102 | 
            +
              version_requirements: *2152736600
         | 
| 103 103 | 
             
            description: ! 'Ruby implementation for Protocol Buffers. Works with other protobuf
         | 
| 104 104 | 
             
              rpc implementations (e.g. Java, Python, C++).
         | 
| 105 105 |  | 
| @@ -180,6 +180,7 @@ files: | |
| 180 180 | 
             
            - proto/rpc.proto
         | 
| 181 181 | 
             
            - protobuf.gemspec
         | 
| 182 182 | 
             
            - script/mk_parser
         | 
| 183 | 
            +
            - spec/benchmark/tasks.rb
         | 
| 183 184 | 
             
            - spec/functional/embedded_service_spec.rb
         | 
| 184 185 | 
             
            - spec/helper/all.rb
         | 
| 185 186 | 
             
            - spec/helper/server.rb
         | 
| @@ -275,6 +276,7 @@ specification_version: 3 | |
| 275 276 | 
             
            summary: Ruby implementation for Protocol Buffers. Works with other protobuf rpc implementations
         | 
| 276 277 | 
             
              (e.g. Java, Python, C++).
         | 
| 277 278 | 
             
            test_files:
         | 
| 279 | 
            +
            - spec/benchmark/tasks.rb
         | 
| 278 280 | 
             
            - spec/functional/embedded_service_spec.rb
         | 
| 279 281 | 
             
            - spec/helper/all.rb
         | 
| 280 282 | 
             
            - spec/helper/server.rb
         |