Raising an exception in on_connect is not really the best way to do
this anyway... Another option is that I could create a decorator for
any server side attributes that require some property of my service to
be True, e.g.

class MyService(rpyc.Service):
   ready = False

   def on_connect(self):
      pass

   @needs_to_be_ready
   @property
   def some_active_property(self):
       """
           This property will only return sensible data if the service is ready
       """
       pass
   exposed_some_active_property = some_active_property

If MyService.ready is False, then accessing some_active_property will
raise an Exception which the client will see.

On 18 June 2012 12:27, Oliver Drake <[email protected]> wrote:
> I'd like to be able to indicate to clients on connection that a
> service is not ready due to something missing/wrong on the server
> side. I thought I would do this by raising an exception in on_connect
> but this didn't have the behaviour I expected, the exception is only
> raised on the server side, the client side connect() call succeeds,
> any subsequent attribute accesses however result in an EOFError. My
> service is only really usable when it is in a specific state which is
> dependent on some other third party software, when my service cannot
> get into the correct state I'd like to be able to raise an appropriate
> exception on the client side that will make it obvious to my users
> that they need to check the server setup.
> I wrote a simple script to illustrate what I'm trying to do:
>
> import rpyc
> from rpyc.utils.server import ThreadedServer
>
> class MyService(rpyc.Service):
>    """
>        Example service that raises ValueError if server/service is not ready
>    """
>    def on_connect(self):
>        """
>            Initialize service - raises ValueError if service not ready
>        """
>        raise ValueError("Service not ready! (Please contact service admin)")
>
>    @property
>    def some_active_property(self):
>        """
>            This property will only return sensible data if the service is 
> ready
>        """
>        raise ValueError("Service is not ready - cannot access active
> properties")
>    exposed_some_active_property = some_active_property
>
> if __name__ == "__main__":
>    t = ThreadedServer(MyService, port=18861)
>    t.start()
>
>
> Client side:
>
> import rpyc
> conn = rpyc.connect("127.0.0.1", 18861)
> print conn.root.some_active_property
>
>
> When running the client side code I get the following outputs:
> Server side:
>
> Exception in thread Thread-1:
> Traceback (most recent call last):
>  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
>    self.run()
>  File "/usr/lib/python2.7/threading.py", line 505, in run
>    self.__target(*self.__args, **self.__kwargs)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/utils/server.py",
> line 165, in _authenticate_and_serve_client
>    self._serve_client(sock2, credentials)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/utils/server.py",
> line 190, in _serve_client
>    conn._init_service()
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/protocol.py",
> line 146, in _init_service
>    self._local_root.on_connect()
>  File "server_side.py", line 13, in on_connect
>    raise ValueError("Service not ready! (Please contact service admin)")
> ValueError: Service not ready! (Please contact service admin)
>
> Client side:
>
> Traceback (most recent call last):
>  File "client_side.py", line 4, in <module>
>    print conn.root.some_active_property
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/protocol.py",
> line 459, in root
>    self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/protocol.py",
> line 430, in sync_request
>    self.serve(0.1)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/protocol.py",
> line 378, in serve
>    data = self._recv(timeout, wait_for_lock = True)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/protocol.py",
> line 336, in _recv
>    data = self._channel.recv()
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/channel.py",
> line 50, in recv
>    header = self.stream.read(self.FRAME_HEADER.size)
>  File "/usr/local/lib/python2.7/dist-packages/rpyc/core/stream.py",
> line 175, in read
>    raise EOFError("connection closed by peer")
> EOFError: connection closed by peer
>
> You can see the client's connect() call worked without exception, the
> client is only made aware of the problem once it tries to access an
> attribute of the service.
> I can think of a few workarounds I could do - e.g. I could always
> allow the client to connect and then add some extra logic in a client
> side wrapper that polls some property on the server side to ensure the
> service is ready for use. However I was thinking this kind of feature
> might be useful to build into the service - in my case it's more
> sensible for the service to decide whether or not it is in a useable
> state - I'd also like to keep the client side code as thin as
> possible.
> Any help/suggestions would be much appreciated :)
> Thanks,
> Oliver

Reply via email to