irmen / Pyrolite

Java and .NET client interface for Pyro5 protocol
MIT License
177 stars 47 forks source link

Asynchronous calls #45

Closed farshidtz closed 7 years ago

farshidtz commented 7 years ago

Hello there,

I'm getting PyroException("result msg out of sync") when calling normal method asynchronously from Java. Is there any way to bypass the sequenceNr checking or is this required for mapping each "result msg" to the callee?

Thanks for the great work! :)

irmen commented 7 years ago

Please show some code that explains how you "call normal method asynchronously". But yeah the exception is thrown when a Pyro(lite) proxy object somehow gets a reply from the server that didn't belong the the request that was sent in that particular thread. You should not use a single Pyro proxy in multiple different threads.

farshidtz commented 7 years ago

I'm calling pyro methods from handlers of an API. In the example below predict can be called multiple times asynchronously. I can use a mutex or synchronized method to force sequential calls but that would cause long queues.

public class ExternPythonPyro {
    PyroProxy pyro;

    public ExternPythonPyro() throws Exception {
        NameServerProxy ns = NameServerProxy.locateNS(null);
        pyro = new PyroProxy(ns.lookup("python-learning-agent"));
        ns.close();
    }

    public void learn(Object input) throws Exception {
        pyro.call_oneway("learn", input);
    }

    public Integer predict(Object input) throws Exception {
        return (Integer) pyro.call("predict", input);
    }

    public void destroy() throws Exception {
        pyro.close();
    }

}

You should not use a single Pyro proxy in multiple different threads.

Is this the case only for Pyrolite or it's a limitation of Pyro in general?

Thanks a lot

irmen commented 7 years ago

It's just the way the underlying socket connections work: they're fully synchronous (blocking) request/replies. The thread using a socket to do a request sits waiting for the response to come back over the same socket. Other threads interfering with the same socket will destroy the integrity of the communication (hence the sequence number check).

Pyro (the python library) does internal locking in its proxies for you. Pyrolite doesn't so you should lock yourself. Or make a pool of proxies where you allocate one per thread.