In my 0MQ applications I usually do this to deal with a timeout:
import zmq
ctx = zmq.Context()
s = ctx.socket(zmq.DEALER)
s.connect("tcp://localhost:5555")
# send PING request
v = <some unique value>
s.send_multipart(["PING", v])
if s.poll(timeout * 1000) & zmq.POLLIN:
msg = s.recv_multipart()
...
However if the server is not running and minutes later goes online, then 0MQ will automatically reconnect and send the message.
However if I put the send PING command in a loop (once a second) and the
server is down, then once the server goes back online I'll get on the next recv_multipart()
-call the old messages
that remained in the internal 0MQ queue while the server was offline. Because I don't care about old
messages, I though I could do this:
s = ctx.socket(zmq.DEALER)
s.connect("tcp://localhost:5555")
while True:
# send PING request
v = <some unique value>
s.send_multipart(["PING", v])
if s.poll(timeout * 1000) & zmq.POLLIN:
msg = s.recv_multipart()
...
else:
s.close()
s = ctx.socket(zmq.DEALER)
s.connect("tcp://localhost:5555")
time.sleep(1)
But this is a bad idea, after a while ctx.socket
raises ZMQError: Too many open files
.
Setting the ZMQ_LINGER
socket option to 0 seems to help
here, but now I don't like this strategy, seems wrong to me.
So ideally I'd like to drop the previously sent message if a read timeout happens. Is this a) possible and b) a good idea at all? I'm not sure that this would be correct though, it may be that 0MQ is able to physically send the message but the server crashes before it can send back anything, so dropping would be impossible because there wouldn't be anything to drop, would it?
So my question is: what should I do in this situation? Am I possibly looking at this problem from the wrong angle?