mbr / tinyrpc

A compact, modular transport and protocol agnostic RPC library. Does jsonrpc v2.
https://tinyrpc.readthedocs.org
MIT License
156 stars 53 forks source link

Is there a way to set up a timeout? #98

Closed darksidds closed 2 years ago

darksidds commented 2 years ago

I'm trying to use ZmqClientTransport and having a problem that if ZmqServerTransport is offline then calling any remote function hangs. Is there a way to set up a timeout on calling functions? Or detect that server is offline?

lnoor commented 2 years ago

I'm afraid not. From tinyrpc's perspective that is a function of the transport layer and ZeroMQ explicitly does not support time outs or connection status querying.

It probably is possible to modify ZmqClientTransport to timeout when not receiving data. But it will only tell you that there was no answer within a given time interval. It won't be able to tell you if the request was not received by the server or the server took a long time to reply or the reply never made it back to the client. I will look into that.

Note to self: use the zmq.Poller class around recv().

darksidds commented 2 years ago

Thanks to you for your prompt and thorough reply!

It won't be able to tell you if the request was not received by the server or the server took a long time to reply or the reply never made it back to the client.

Falling with timeout exception is much better than eternal await.

lnoor commented 2 years ago

Sorry it took so long, i got sick. In the branch https://github.com/mbr/tinyrpc/tree/lnoor/zmq-timeout is a version of ZmqClientTransport with a timeout parameter in the constructor and create functions. This optional parameter takes an integer value of milliseconds for the timeout. Can you please try this branch and verify that it serves your purpose?

darksidds commented 2 years ago

Your patch looks fine.

  1. The client works just as you described earlier. It doesn't matter whether the server is offline or works too slowly - we still get a TimeoutException after timeout milliseconds.
  2. Timeout in milliseconds is not a pythonic way. It should be in seconds otherwise documented.
  3. Keyboard Interrupt works somewhat weird. Let's say I have a 50-second timeout and function that takes 40 seconds to execute, then if I key in Ctrl+C, my program aborts only after 40 seconds.
    Traceback (most recent call last):
    File "C:\sandbox\tinyrpc_client.py", line 38, in <module>
    x = str_server.long_command(40.510)
    File "C:\sandbox\test-venv\lib\site-packages\tinyrpc\client.py", line 177, in <lambda>
    proxy_func = lambda *args, **kwargs: self.client.call(
    File "C:\sandbox\test-venv\lib\site-packages\tinyrpc\client.py", line 89, in call
    rep = self._send_and_handle_reply(req, one_way)
    File "C:\sandbox\test-venv\lib\site-packages\tinyrpc\client.py", line 52, in _send_and_handle_reply
    reply = tport.send_message(req.serialize(), expect_reply=(not one_way))
    File "C:\sandbox\test-venv\lib\site-packages\tinyrpc\transports\zmq.py", line 74, in send_message
    ready = dict(poller.poll(self.timeout))
    File "C:\sandbox\test-venv\lib\site-packages\zmq\sugar\poll.py", line 105, in poll
    return zmq_poll(self.sockets, timeout=timeout)
    File "zmq\backend\cython\_poll.pyx", line 117, in zmq.backend.cython._poll.zmq_poll
    File "zmq\backend\cython\checkrc.pxd", line 13, in zmq.backend.cython.checkrc._check_rc
    KeyboardInterrupt
lnoor commented 2 years ago
  1. Please note that on timeout you will not know if the request was received and processed by the server or that the result wasn't returned to the client. This means that it is entirely possible that the request was processed normally and should not be resend unless you make certain that this possibility is detected and handled.
  2. Adapted. Python's select.poll() wants milliseconds and zmq is modeled after it. However other delays including the timeout in requests (used in the http client) use secods. Therefore seconds is the better unit indeed.
  3. I'm afraid I cannot really help with that, it looks like something in the zmq library or ffi is causing this.

Thanks for the feedback. I will create a new version of tinyrpc and upload it to pypi.

darksidds commented 2 years ago

Thank you for the support!