em-zmq-tp10 0.1.7
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/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +237 -0
- data/Rakefile +9 -0
- data/em-zmq-tp10.gemspec +23 -0
- data/lib/em-zmq-tp10.rb +1 -0
- data/lib/em/protocols/zmq2.rb +25 -0
- data/lib/em/protocols/zmq2/connection.rb +37 -0
- data/lib/em/protocols/zmq2/dealer.rb +133 -0
- data/lib/em/protocols/zmq2/inproc.rb +147 -0
- data/lib/em/protocols/zmq2/pub_sub.rb +102 -0
- data/lib/em/protocols/zmq2/queue_per_peer.rb +57 -0
- data/lib/em/protocols/zmq2/rep.rb +64 -0
- data/lib/em/protocols/zmq2/req.rb +325 -0
- data/lib/em/protocols/zmq2/router.rb +69 -0
- data/lib/em/protocols/zmq2/socket.rb +236 -0
- data/lib/em/protocols/zmq2/socket_connection.rb +151 -0
- data/lib/em/protocols/zmq2/version.rb +7 -0
- data/lib/em/protocols/zmq_tp10.rb +2 -0
- data/tests/helper.rb +102 -0
- data/tests/run_all.rb +3 -0
- data/tests/test_dealer.rb +237 -0
- data/tests/test_inproc.rb +113 -0
- data/tests/test_pub_sub.rb +271 -0
- data/tests/test_reconnect.rb +64 -0
- data/tests/test_rep.rb +117 -0
- data/tests/test_req.rb +229 -0
- data/tests/test_router.rb +221 -0
- metadata +108 -0
    
        data/tests/test_req.rb
    ADDED
    
    | @@ -0,0 +1,229 @@ | |
| 1 | 
            +
            require 'eventmachine'
         | 
| 2 | 
            +
            require 'minitest/autorun'
         | 
| 3 | 
            +
            require File.expand_path('../helper.rb', __FILE__)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'em/protocols/zmq2/req'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe 'Req' do
         | 
| 8 | 
            +
              let(:connected) do
         | 
| 9 | 
            +
                EM::DefaultDeferrable.new
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              describe EM::Protocols::Zmq2::PreReq do
         | 
| 13 | 
            +
                class MyPreReq < EM::Protocols::Zmq2::PreReq
         | 
| 14 | 
            +
                  attr :incoming_queue
         | 
| 15 | 
            +
                  def initialize(opts={})
         | 
| 16 | 
            +
                    super
         | 
| 17 | 
            +
                    @connected = opts[:connected]
         | 
| 18 | 
            +
                    @incoming_queue = []
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  def peer_free(peer_identity, connection)
         | 
| 21 | 
            +
                    super
         | 
| 22 | 
            +
                    @connected.succeed
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                  def receive_reply(message, data, request_id)
         | 
| 25 | 
            +
                    message.first.must_equal 'world'
         | 
| 26 | 
            +
                    message.last.must_equal data.to_s
         | 
| 27 | 
            +
                    @incoming_queue << ['hello', message.last]
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                attr :req
         | 
| 32 | 
            +
                before do
         | 
| 33 | 
            +
                  @req = MyPreReq.new(identity: 'REQ', connected: connected)
         | 
| 34 | 
            +
                  @req.connect(Native::ZBIND_ADDR)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                let(:messages){
         | 
| 38 | 
            +
                  300.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
         | 
| 39 | 
            +
                }
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                it 'should send requests' do
         | 
| 42 | 
            +
                  Native.with_socket('REP') do |zrep|
         | 
| 43 | 
            +
                    thrd = Thread.new do
         | 
| 44 | 
            +
                      messages.size.times do
         | 
| 45 | 
            +
                        ar = []
         | 
| 46 | 
            +
                        zrep.recv_strings ar
         | 
| 47 | 
            +
                        ar[0] = 'world'
         | 
| 48 | 
            +
                        zrep.send_strings ar
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                    EM.run {
         | 
| 52 | 
            +
                      connected.callback {
         | 
| 53 | 
            +
                        dup = messages.dup
         | 
| 54 | 
            +
                        cb = lambda {
         | 
| 55 | 
            +
                          if dup.empty?
         | 
| 56 | 
            +
                            EM.add_timer(0.3){
         | 
| 57 | 
            +
                              EM.next_tick{ EM.stop }
         | 
| 58 | 
            +
                            }
         | 
| 59 | 
            +
                          else
         | 
| 60 | 
            +
                            message = dup.first
         | 
| 61 | 
            +
                            if String === req.send_request(message, message.last)
         | 
| 62 | 
            +
                              dup.shift
         | 
| 63 | 
            +
                              EM.next_tick cb
         | 
| 64 | 
            +
                            else
         | 
| 65 | 
            +
                              EM.add_timer 0.1, cb
         | 
| 66 | 
            +
                            end
         | 
| 67 | 
            +
                          end
         | 
| 68 | 
            +
                        }
         | 
| 69 | 
            +
                        cb.call
         | 
| 70 | 
            +
                      }
         | 
| 71 | 
            +
                    }
         | 
| 72 | 
            +
                    thrd.join
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                  (req.incoming_queue - messages).must_be_empty
         | 
| 75 | 
            +
                  (messages - req.incoming_queue).must_be_empty
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              describe EM::Protocols::Zmq2::Req do
         | 
| 80 | 
            +
                class MyReq < EM::Protocols::Zmq2::Req
         | 
| 81 | 
            +
                  attr :incoming_queue, :canceled_requests
         | 
| 82 | 
            +
                  def initialize(opts={}, defered_conn, defered_mess)
         | 
| 83 | 
            +
                    super opts
         | 
| 84 | 
            +
                    @defered_conn = defered_conn
         | 
| 85 | 
            +
                    @defered_mess = defered_mess
         | 
| 86 | 
            +
                    @incoming_queue = []
         | 
| 87 | 
            +
                    @canceled_requests = []
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                  def peer_free(peer_identity, connection)
         | 
| 90 | 
            +
                    super
         | 
| 91 | 
            +
                    @defered_conn.succeed
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
                  def receive_reply(message, data, request_id)
         | 
| 94 | 
            +
                    message.first.must_equal 'world'
         | 
| 95 | 
            +
                    message.last.must_equal data.to_s
         | 
| 96 | 
            +
                    @incoming_queue << ['hello', message.last]
         | 
| 97 | 
            +
                    @defered_mess.succeed  if message.last == 'xxx'
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                  def cancel_request(request_id)
         | 
| 100 | 
            +
                    @canceled_requests << request_id
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                let(:finished){ EM::DefaultDeferrable.new }
         | 
| 105 | 
            +
                attr :req
         | 
| 106 | 
            +
                before do
         | 
| 107 | 
            +
                  @req = MyReq.new({identity: 'REQ'}, connected, finished)
         | 
| 108 | 
            +
                  @req.connect(Native::ZBIND_ADDR)
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
                let(:messages){
         | 
| 111 | 
            +
                  5000.times.map{|i| ['hello', i.to_s]} << ['hello', 'xxx']
         | 
| 112 | 
            +
                }
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                it 'should send a lot of requests' do
         | 
| 115 | 
            +
                  Native.with_socket('REP') do |zrep|
         | 
| 116 | 
            +
                    thrd = Thread.new do
         | 
| 117 | 
            +
                      messages.size.times do
         | 
| 118 | 
            +
                        ar = []
         | 
| 119 | 
            +
                        zrep.recv_strings ar
         | 
| 120 | 
            +
                        ar[0] = 'world'
         | 
| 121 | 
            +
                        zrep.send_strings ar
         | 
| 122 | 
            +
                      end
         | 
| 123 | 
            +
                    end
         | 
| 124 | 
            +
                    EM.run {
         | 
| 125 | 
            +
                      connected.callback {
         | 
| 126 | 
            +
                        messages.each{|message|
         | 
| 127 | 
            +
                          req.send_request(message, message.last)
         | 
| 128 | 
            +
                        }
         | 
| 129 | 
            +
                      }
         | 
| 130 | 
            +
                      finished.callback {
         | 
| 131 | 
            +
                        EM.next_tick{ EM.stop }
         | 
| 132 | 
            +
                      }
         | 
| 133 | 
            +
                    }
         | 
| 134 | 
            +
                    thrd.join
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
                  (req.incoming_queue - messages).must_be_empty
         | 
| 137 | 
            +
                  (messages - req.incoming_queue).must_be_empty
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                it "should not accept message on low hwm with strategy :drop_last" do
         | 
| 141 | 
            +
                  req.hwm = 2
         | 
| 142 | 
            +
                  req.hwm_strategy = :drop_last
         | 
| 143 | 
            +
                  EM.run {
         | 
| 144 | 
            +
                    req.send_request(['hi', 'ho1'], nil).must_be_kind_of String
         | 
| 145 | 
            +
                    req.send_request(['hi', 'ho2'], nil).must_be_kind_of String
         | 
| 146 | 
            +
                    req.send_request(['hi', 'ho3'], nil).wont_be_kind_of String
         | 
| 147 | 
            +
                    EM.stop
         | 
| 148 | 
            +
                  }
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                it "should cancel earlier message on low hwm with strategy :drop_first" do
         | 
| 152 | 
            +
                  req.hwm = 2
         | 
| 153 | 
            +
                  req.hwm_strategy = :drop_first
         | 
| 154 | 
            +
                  first_req = nil
         | 
| 155 | 
            +
                  EM.run {
         | 
| 156 | 
            +
                    first_req = req.send_request(['hi', 'ho1'], nil)
         | 
| 157 | 
            +
                    first_req.must_be_kind_of String
         | 
| 158 | 
            +
                    req.send_request(['hi', 'ho2'], nil).must_be_kind_of String
         | 
| 159 | 
            +
                    req.send_request(['hi', 'ho3'], nil).must_be_kind_of String
         | 
| 160 | 
            +
                    EM.stop
         | 
| 161 | 
            +
                  }
         | 
| 162 | 
            +
                  req.canceled_requests.must_equal [first_req]
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
              end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
              describe EM::Protocols::Zmq2::ReqDefer do
         | 
| 167 | 
            +
                class TSTRep < EM::Protocols::Zmq2::Rep
         | 
| 168 | 
            +
                  include DeferredMixin
         | 
| 169 | 
            +
                  def receive_request(message, environment)
         | 
| 170 | 
            +
                    send_reply([message.first, 'yeah'], environment)
         | 
| 171 | 
            +
                  end
         | 
| 172 | 
            +
                  def peer_free(peer, conn)
         | 
| 173 | 
            +
                    super
         | 
| 174 | 
            +
                    @connected.succeed
         | 
| 175 | 
            +
                  end
         | 
| 176 | 
            +
                end
         | 
| 177 | 
            +
                it "should correctly setup and call deferrable" do
         | 
| 178 | 
            +
                  req = EM::Protocols::Zmq2::ReqDefer.new
         | 
| 179 | 
            +
                  def req.send_message(message, even = false)
         | 
| 180 | 
            +
                    res = super
         | 
| 181 | 
            +
                    res
         | 
| 182 | 
            +
                  end
         | 
| 183 | 
            +
                  rep = TSTRep.new(connected: connected)
         | 
| 184 | 
            +
                  rep.bind('inproc://tst')
         | 
| 185 | 
            +
                  first_success, first_error = nil, nil
         | 
| 186 | 
            +
                  second_success, second_error = nil, nil
         | 
| 187 | 
            +
                      require 'pp'
         | 
| 188 | 
            +
                  EM.run {
         | 
| 189 | 
            +
                    uniq = Object.new.freeze
         | 
| 190 | 
            +
                    first = nil
         | 
| 191 | 
            +
                    follow = proc do |null, data|
         | 
| 192 | 
            +
                      data.must_equal uniq
         | 
| 193 | 
            +
                      null.must_be_nil
         | 
| 194 | 
            +
                      req.connect('inproc://tst')
         | 
| 195 | 
            +
                      connected.callback do
         | 
| 196 | 
            +
                        stop = proc{ EM.next_tick{ EM.stop } }
         | 
| 197 | 
            +
                        second = req.send_request(['hi', 'ho'], uniq) do |reply, data|
         | 
| 198 | 
            +
                          second_success = true
         | 
| 199 | 
            +
                          reply.must_equal ['hi', 'yeah']
         | 
| 200 | 
            +
                          data.must_equal uniq
         | 
| 201 | 
            +
                        end
         | 
| 202 | 
            +
                        second.must_be_kind_of EM::Deferrable
         | 
| 203 | 
            +
                        second.errback do
         | 
| 204 | 
            +
                          second_error = true
         | 
| 205 | 
            +
                        end
         | 
| 206 | 
            +
                        second.callback &stop
         | 
| 207 | 
            +
                        second.errback &stop
         | 
| 208 | 
            +
                      end
         | 
| 209 | 
            +
                    end
         | 
| 210 | 
            +
                    first = req.send_request(['hi', 'ho'], uniq) do |reply, data|
         | 
| 211 | 
            +
                      first_success = true
         | 
| 212 | 
            +
                      reply.must_equal ['hi', 'yeah']
         | 
| 213 | 
            +
                      data.must_equal uniq
         | 
| 214 | 
            +
                    end
         | 
| 215 | 
            +
                    first.must_be_kind_of EM::Deferrable
         | 
| 216 | 
            +
                    first.timeout(0.3, 1, uniq)
         | 
| 217 | 
            +
                    first.errback do
         | 
| 218 | 
            +
                      first_error = true
         | 
| 219 | 
            +
                    end
         | 
| 220 | 
            +
                    first.callback &follow
         | 
| 221 | 
            +
                    first.errback &follow
         | 
| 222 | 
            +
                  }
         | 
| 223 | 
            +
                  first_success.must_equal nil
         | 
| 224 | 
            +
                  first_error.must_equal true
         | 
| 225 | 
            +
                  second_success.must_equal true
         | 
| 226 | 
            +
                  second_error.must_equal nil
         | 
| 227 | 
            +
                end
         | 
| 228 | 
            +
              end
         | 
| 229 | 
            +
            end
         | 
| @@ -0,0 +1,221 @@ | |
| 1 | 
            +
            require 'eventmachine'
         | 
| 2 | 
            +
            require 'minitest/autorun'
         | 
| 3 | 
            +
            require File.expand_path('../helper.rb', __FILE__)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'em/protocols/zmq2/router'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe 'Router' do
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              let(:connected) do
         | 
| 10 | 
            +
                EM::DefaultDeferrable.new
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              let(:finished) do
         | 
| 14 | 
            +
                EM::DefaultDeferrable.new
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              class DealerCollector
         | 
| 18 | 
            +
                attr :res_a, :res_b
         | 
| 19 | 
            +
                def initialize(till)
         | 
| 20 | 
            +
                  @till = till
         | 
| 21 | 
            +
                  @res_a, @res_b = [], []
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                def full?
         | 
| 24 | 
            +
                  @res_a.size + @res_b.size >= @till
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                def full_res
         | 
| 27 | 
            +
                  @res_a + @res_b
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                def set_sockets(zbind, zconnect)
         | 
| 30 | 
            +
                  @zbind = zbind
         | 
| 31 | 
            +
                  @zconnect = zconnect
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
                def thread
         | 
| 34 | 
            +
                  Thread.new do
         | 
| 35 | 
            +
                    begin
         | 
| 36 | 
            +
                    result = []
         | 
| 37 | 
            +
                    until full?
         | 
| 38 | 
            +
                      while @zbind.recv_strings(result, ZMQ::NOBLOCK) != -1
         | 
| 39 | 
            +
                        result.first.must_equal 'hello'
         | 
| 40 | 
            +
                        @res_a << result
         | 
| 41 | 
            +
                        result = []
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
                      while @zconnect.recv_strings(result, ZMQ::NOBLOCK) != -1
         | 
| 44 | 
            +
                        result.first.must_equal 'hello'
         | 
| 45 | 
            +
                        @res_b << result
         | 
| 46 | 
            +
                        result = []
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                      sleep(0.01)
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
                    rescue
         | 
| 51 | 
            +
                      puts $!
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              describe EM::Protocols::Zmq2::PreRouter do
         | 
| 58 | 
            +
                class MyPreRouter < EM::Protocols::Zmq2::PreRouter
         | 
| 59 | 
            +
                  attr :incoming_queue
         | 
| 60 | 
            +
                  def initialize(connected, finished, opts={})
         | 
| 61 | 
            +
                    super opts
         | 
| 62 | 
            +
                    @connected = connected
         | 
| 63 | 
            +
                    @finished = finished
         | 
| 64 | 
            +
                    @incoming_queue = {}
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                  def peer_free(peer_ident, connection)
         | 
| 67 | 
            +
                    super
         | 
| 68 | 
            +
                    @connected.succeed  if @free_peers.size == 2
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                  def receive_message(message)
         | 
| 71 | 
            +
                    (@incoming_queue[message.first] ||= []) << message[1..-1]
         | 
| 72 | 
            +
                    @finished.succeed  if message.last == 'xxx'
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                attr :router
         | 
| 77 | 
            +
                before do
         | 
| 78 | 
            +
                  @router = MyPreRouter.new(connected, finished, identity: 'MyRouter')
         | 
| 79 | 
            +
                  @router.bind(Native::ZCONNECT_ADDR)
         | 
| 80 | 
            +
                  @router.connect(Native::ZBIND_ADDR)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                let(:messages) do
         | 
| 84 | 
            +
                  62.times.map{|n| ['hello', n.to_s] } << ['hello', 'xxx']
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                it "should be able to receive messages" do
         | 
| 88 | 
            +
                  halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
         | 
| 89 | 
            +
                  Native.with_socket_pair('DEALER') do |zbind, zconnect|
         | 
| 90 | 
            +
                    EM.run {
         | 
| 91 | 
            +
                      connected.callback do
         | 
| 92 | 
            +
                        halves[0].each do |message|
         | 
| 93 | 
            +
                          zbind.send_strings(message)
         | 
| 94 | 
            +
                        end
         | 
| 95 | 
            +
                        halves[1].each do |message|
         | 
| 96 | 
            +
                          zconnect.send_strings(message)
         | 
| 97 | 
            +
                        end
         | 
| 98 | 
            +
                      end
         | 
| 99 | 
            +
                      finished.callback do
         | 
| 100 | 
            +
                        EM.next_tick{ EM.stop }
         | 
| 101 | 
            +
                      end
         | 
| 102 | 
            +
                    }
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                  router.incoming_queue['BIND_DEALER'].must_equal halves[0]
         | 
| 105 | 
            +
                  router.incoming_queue['CONNECT_DEALER'].must_equal halves[1]
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                it "should be able to route messages" do
         | 
| 109 | 
            +
                  collector = DealerCollector.new(messages.size)
         | 
| 110 | 
            +
                  halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
         | 
| 111 | 
            +
                  Native.with_socket_pair('DEALER') do |zbind, zconnect|
         | 
| 112 | 
            +
                    collector.set_sockets zbind, zconnect
         | 
| 113 | 
            +
                    thrd = collector.thread
         | 
| 114 | 
            +
                    EM.run {
         | 
| 115 | 
            +
                      dup_halves = halves.map(&:dup)
         | 
| 116 | 
            +
                      connected.callback do
         | 
| 117 | 
            +
                        dup_halves[0].each do |message|
         | 
| 118 | 
            +
                          router.send_message(['BIND_DEALER', *message]).must_equal true
         | 
| 119 | 
            +
                        end
         | 
| 120 | 
            +
                        dup_halves[1].each do |message|
         | 
| 121 | 
            +
                          router.send_message(['CONNECT_DEALER', *message]).must_equal true
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
                        EM.defer(proc do thrd.join end, proc do
         | 
| 124 | 
            +
                          EM.next_tick{ EM.stop }
         | 
| 125 | 
            +
                        end)
         | 
| 126 | 
            +
                      end
         | 
| 127 | 
            +
                    }
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                  collector.res_a.must_equal halves[0]
         | 
| 130 | 
            +
                  collector.res_b.must_equal halves[1]
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
              end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
              describe EM::Protocols::Zmq2::Router do
         | 
| 135 | 
            +
                class MyRouter < EM::Protocols::Zmq2::Router
         | 
| 136 | 
            +
                  attr :incoming_queue, :canceled_messages
         | 
| 137 | 
            +
                  def initialize(connected, finished, opts={})
         | 
| 138 | 
            +
                    super opts
         | 
| 139 | 
            +
                    @connected = connected
         | 
| 140 | 
            +
                    @finished = finished
         | 
| 141 | 
            +
                    @incoming_queue = {}
         | 
| 142 | 
            +
                    @canceled_messages = []
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
                  def peer_free(peer_ident, connection)
         | 
| 145 | 
            +
                    super
         | 
| 146 | 
            +
                    @connected.succeed  if @free_peers.size == 2
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
                  def receive_message(message)
         | 
| 149 | 
            +
                    (@incoming_queue[message.first] ||= []) << message[1..-1]
         | 
| 150 | 
            +
                    @finished.succeed  if message.last == 'xxx'
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
                  def cancel_message(message)
         | 
| 153 | 
            +
                    @canceled_messages << message
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                attr :router
         | 
| 158 | 
            +
                before do
         | 
| 159 | 
            +
                  @router = MyRouter.new(connected, finished, identity: 'MyRouter')
         | 
| 160 | 
            +
                  @router.bind(Native::ZCONNECT_ADDR)
         | 
| 161 | 
            +
                  @router.connect(Native::ZBIND_ADDR)
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                let(:messages) do
         | 
| 165 | 
            +
                  10000.times.map{|n| ['hello', n.to_s] } << ['hello', 'xxx']
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                it "should be able to route a lot of messages" do
         | 
| 169 | 
            +
                  collector = DealerCollector.new(messages.size)
         | 
| 170 | 
            +
                  halves = messages[0...(messages.size/2)], messages[(messages.size/2)..-1]
         | 
| 171 | 
            +
                  Native.with_socket_pair('DEALER') do |zbind, zconnect|
         | 
| 172 | 
            +
                    collector.set_sockets zbind, zconnect
         | 
| 173 | 
            +
                    thrd = collector.thread
         | 
| 174 | 
            +
                    EM.run {
         | 
| 175 | 
            +
                      dup_halves = halves.map(&:dup)
         | 
| 176 | 
            +
                      connected.callback do
         | 
| 177 | 
            +
                        dup_halves[0].each do |message|
         | 
| 178 | 
            +
                          router.send_message(['BIND_DEALER', *message])
         | 
| 179 | 
            +
                        end
         | 
| 180 | 
            +
                        dup_halves[1].each do |message|
         | 
| 181 | 
            +
                          router.send_message(['CONNECT_DEALER', *message])
         | 
| 182 | 
            +
                        end
         | 
| 183 | 
            +
                        EM.defer(proc do thrd.join end, proc do
         | 
| 184 | 
            +
                          EM.next_tick{ EM.stop }
         | 
| 185 | 
            +
                        end)
         | 
| 186 | 
            +
                      end
         | 
| 187 | 
            +
                    }
         | 
| 188 | 
            +
                    thrd.join
         | 
| 189 | 
            +
                  end
         | 
| 190 | 
            +
                  collector.res_a.must_equal halves[0]
         | 
| 191 | 
            +
                  collector.res_b.must_equal halves[1]
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                it "should not accept message on low hwm with strategy :drop_last" do
         | 
| 195 | 
            +
                  router.hwm = 1
         | 
| 196 | 
            +
                  router.hwm_strategy = :drop_last
         | 
| 197 | 
            +
                  EM.run {
         | 
| 198 | 
            +
                    router.send_message(['FIRST_PEER', 'hi', 'ho1']).must_equal true
         | 
| 199 | 
            +
                    router.send_message(['FIRST_PEER', 'hi', 'ho2']).wont_equal true
         | 
| 200 | 
            +
                    router.send_message(['SECOND_PEER', 'hi', 'ho1']).must_equal true
         | 
| 201 | 
            +
                    router.send_message(['SECOND_PEER', 'hi', 'ho2']).wont_equal true
         | 
| 202 | 
            +
                    EM.stop
         | 
| 203 | 
            +
                  }
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                it "should cancel earlier message on low hwm with strategy :drop_first" do
         | 
| 207 | 
            +
                  router.hwm = 1
         | 
| 208 | 
            +
                  router.hwm_strategy = :drop_first
         | 
| 209 | 
            +
                  EM.run {
         | 
| 210 | 
            +
                    router.send_message(['FIRST_PEER', 'hi', 'ho1']).must_equal true
         | 
| 211 | 
            +
                    router.send_message(['FIRST_PEER', 'hi', 'ho2']).must_equal true
         | 
| 212 | 
            +
                    router.send_message(['SECOND_PEER', 'hi', 'ho1']).must_equal true
         | 
| 213 | 
            +
                    router.send_message(['SECOND_PEER', 'hi', 'ho2']).must_equal true
         | 
| 214 | 
            +
                    EM.stop
         | 
| 215 | 
            +
                  }
         | 
| 216 | 
            +
                  router.canceled_messages.count.must_equal 2
         | 
| 217 | 
            +
                  router.canceled_messages.must_include ['FIRST_PEER', 'hi', 'ho1']
         | 
| 218 | 
            +
                  router.canceled_messages.must_include ['SECOND_PEER', 'hi', 'ho1']
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
              end
         | 
| 221 | 
            +
            end
         |