From e7fa419f13e0afbb3f2653a4b0d8330dd45bbfd0 Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 24 Jul 2013 17:51:03 -0300 Subject: Add doc and tests about events sync/async behaviour. * Also fix docstrings identation so sphynx doesn't complain. --- src/leap/common/events/__init__.py | 82 +++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 18 deletions(-) (limited to 'src/leap/common/events/__init__.py') diff --git a/src/leap/common/events/__init__.py b/src/leap/common/events/__init__.py index 388ee17..a6fe7c3 100644 --- a/src/leap/common/events/__init__.py +++ b/src/leap/common/events/__init__.py @@ -16,7 +16,58 @@ # along with this program. If not, see . """ -An events mechanism that allows for signaling of events between clients. +This is an events mechanism that uses a server to allow for signaling of +events between clients. + +Application components should use the interface available in this file to +register callbacks to be executed upon receiving specific signals, and to send +signals to other components. + +To register a callback to be executed when a specific event is signaled, use +leap.common.events.register(): + +>>> from leap.common.events import register +>>> from leap.common.events.proto import CLIENT_UID +>>> register(CLIENT_UID, lambda req: do_something(req)) + +To signal an event, use leap.common.events.signal(): + +>>> from leap.common.events import signal +>>> from leap.common.events.proto import CLIENT_UID +>>> signal(CLIENT_UID) + + +NOTE ABOUT SYNC/ASYNC REQUESTS: + +Clients always communicate with the server, and never between themselves. +When a client registers a callback for an event, the callback is saved locally +in the client and the server stores the client socket port in a list +associated with that event. When a client signals an event, the server +forwards the signal to all registered client ports, and then each client +executes its callbacks associated with that event locally. + +Each RPC call from a client to the server is followed by a response from the +server to the client. Calls to register() and signal() (and all other RPC +calls) can be synchronous or asynchronous meaning if they will or not wait for +the server's response before returning. + +This mechanism was built on top of protobuf.socketrpc, and because of this RPC +calls are made synchronous or asynchronous in the following way: + + * If RPC calls receive a parameter called `reqcbk`, then the call is made + asynchronous. That means that: + + - an eventual `timeout` parameter is not used, + - the call returns immediatelly with value None, and + - the `reqcbk` callback is executed asynchronously upon the arrival of + a response from the server. + + * Otherwise, if the `reqcbk` parameter is None, then the call is made in a + synchronous manner: + + - if a response from server arrives within `timeout` milliseconds, the + RPC call returns it; + - otherwise, the call returns None. """ import logging @@ -54,9 +105,8 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, :param replace: should an existent callback with same uid be replaced? :type replace: bool :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) + received + :type reqcbk: function(leap.common.events.events_pb2.EventResponse) :param timeout: the timeout for synch calls :type timeout: int @@ -79,14 +129,13 @@ def unregister(signal, uid=None, reqcbk=None, timeout=1000): :param uid: a unique id for the callback :type uid: int :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) + received + :type reqcbk: function(leap.common.events.events_pb2.EventResponse) :param timeout: the timeout for synch calls :type timeout: int :return: the response from server for synch calls or nothing for asynch - calls. + calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ return client.unregister(signal, uid, reqcbk, timeout) @@ -112,14 +161,13 @@ def signal(signal, content="", mac_method="", mac="", reqcbk=None, :param mac: the content of the auth mac :type mac: str :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) + received + :type reqcbk: function(leap.common.events.events_pb2.EventResponse) :param timeout: the timeout for synch calls :type timeout: int :return: the response from server for synch calls or nothing for asynch - calls. + calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ return client.signal(signal, content, mac_method, mac, reqcbk, timeout) @@ -131,9 +179,8 @@ def ping_client(port, reqcbk=None, timeout=1000): :param port: the port in which the client should be listening :type port: int :param reqcbk: a callback to be called when a response from client is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) + received + :type reqcbk: function(leap.common.events.events_pb2.EventResponse) :param timeout: the timeout for synch calls :type timeout: int """ @@ -147,9 +194,8 @@ def ping_server(port=server.SERVER_PORT, reqcbk=None, timeout=1000): :param port: the port in which server should be listening :type port: int :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) + received + :type reqcbk: function(leap.common.events.events_pb2.EventResponse) :param timeout: the timeout for synch calls :type timeout: int """ -- cgit v1.2.3