Search code examples
pythonasynchronouszeromqzerorpc

Zerorpc asynchronous calls


Server

Suppose I have the following zerorpc server

#server side
import zerorpc

class API():

    def long_running_task(self):
        print('1 - started long_running_task')
        #for instance a long running SQL query
        zerorpc.gevent.sleep(10)
        print('2 - finished long_running_task')

    def other_task(self):
        print('1 - started other_task')
        pass
        print('2 - finished other_task')

s = zerorpc.Server(API())
s.bind("tcp://0.0.0.0:4444")
zerorpc.gevent.spawn(s.run)
while True:
    zerorpc.gevent.sleep(10)

Client

and a client app which sends several requests simultanously

import zerorpc

client = zerorpc.Client()
client.connect("tcp://127.0.0.1:4444")

client.long_running_task(async_=True)
client.other_task(async_=True)

client.close()

The problem is that while the long_running_task is being executed the other_task doesn't start running.

The desired output is:

1 - started long_running_task
1 - started other_task
2 - finished other_task
2 - finished long_running_task

instead of

1 - started long_running_task
2 - finished long_running_task
1 - started other_task
2 - finished other_task

Solution

  • There are a few mistakes here

    1. async_ should be async. This ensures client method returns immediately
    2. ZeroRPC works with gevent. So you need to start the server with gevent.spawn(s.run). Also to keep your main greenlet running.
    zerorpc.gevent.spawn(s.run)
    while True:
         zerorpc.gevent.sleep(10)
    
    1. above 2 is not enough. In the API() methods you need to be co-operative too. Instead of time.sleep() use gevent.sleep().