nflacco
nflacco

Reputation: 5082

ruby - zeromq detects client timeout, but client hangs

I'm trying to write a simple zmq system to replace an http client/server. My client times out when the server is off/unavailable, but does not retry or stop. What am I missing?

zmq_client.rb (modified version of Han Holl's lazy pirate client from zeromq guide)

require 'rubygems'
require 'zmq'

context = ZMQ::Context.new
socket = context.socket(ZMQ::REQ)
socket.connect('tcp://localhost:5559')

retries = 2
timeout = 10

retries.times do |tries|
  message = "Hello #{tries}"
  raise("Send: #{message} failed") unless socket.send(message)
  puts "Sending string [#{message}]"

  if ZMQ.select( [socket], nil, nil, timeout)
    message = socket.recv
    puts "Received reply [#{message}]"
    break
  else
    puts "timeout"
  end

end
socket.close

zmq_broker.rb (modified version of Oleg Sidorov's code found on zeromq guide)

require 'rubygems'
require 'ffi-rzmq'

context = ZMQ::Context.new
frontend = context.socket(ZMQ::ROUTER)
frontend.bind('tcp://*:5559')
poller = ZMQ::Poller.new
poller.register(frontend, ZMQ::POLLIN)

loop do
  poller.poll(:blocking)
  poller.readables.each do |socket|
    if socket === frontend
      loop do
        socket.recv_string(message = '')
        more = socket.more_parts?
        puts "#{message}#{more}"
        socket.send_string(message, more ? ZMQ::SNDMORE : 0)
        break unless more
      end
    end
  end
end

Upvotes: 1

Views: 1085

Answers (1)

vond
vond

Reputation: 1948

You should get an error Send: #{message} failed as soon as you try to send again after the first timeout, because your 2nd send will happen directly after the 1st send, and the REQ socket enforces that each send must go after (successful, not timeout-ed) recv.

In the lazy pirate pattern, you may need to send several requests before getting a reply. Solution suggested in the 0MQ Guide is to close and reopen the REQ socket after an error. Your client doesn't close/reopen the REQ socket.

You may find helpful the "Lazy Pirate client in Ruby" example from the Guide.

Upvotes: 1

Related Questions