diff sat/bridge/pb.py @ 3039:a1bc34f90fa5

bridge (pb): implemented an asyncio compatible bridge: `pb` bridge can now be used with asyncio by instantiating AIOBridge.
author Goffi <goffi@goffi.org>
date Wed, 25 Sep 2019 08:53:38 +0200
parents ab2696e34d29
children 9d0df638c8b4
line wrap: on
line diff
--- a/sat/bridge/pb.py	Wed Sep 25 08:41:36 2019 +0200
+++ b/sat/bridge/pb.py	Wed Sep 25 08:53:38 2019 +0200
@@ -18,10 +18,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+import dataclasses
 from sat.core.log import getLogger
-
 from twisted.spread import jelly, pb
 from twisted.internet import reactor
+
 log = getLogger(__name__)
 
 
@@ -40,34 +41,41 @@
 jelly._Jellier.jelly = fixed_jelly
 
 
+@dataclasses.dataclass(eq=False)
+class HandlerWrapper:
+    # we use a wrapper to keep signals handlers because RemoteReference doesn't support
+    # comparison (other than equality), making it unusable with a list
+    handler: pb.RemoteReference
+
+
 class PBRoot(pb.Root):
     def __init__(self):
         self.signals_handlers = []
 
     def remote_initBridge(self, signals_handler):
-        self.signals_handlers.append(signals_handler)
+        self.signals_handlers.append(HandlerWrapper(signals_handler))
         log.info("registered signal handler")
 
-    def sendSignalEb(self, failure, signal_name):
-        log.error(
-            "Error while sending signal {name}: {msg}".format(
-                name=signal_name, msg=failure
+    def sendSignalEb(self, failure_, signal_name):
+        if not failure_.check(pb.PBConnectionLost):
+            log.error(
+                f"Error while sending signal {signal_name}: {failure_}",
             )
-        )
 
     def sendSignal(self, name, args, kwargs):
         to_remove = []
-        for handler in self.signals_handlers:
+        for wrapper in self.signals_handlers:
+            handler = wrapper.handler
             try:
                 d = handler.callRemote(name, *args, **kwargs)
             except pb.DeadReferenceError:
-                to_remove.append(handler)
+                to_remove.append(wrapper)
             else:
                 d.addErrback(self.sendSignalEb, name)
         if to_remove:
-            for handler in to_remove:
+            for wrapper in to_remove:
                 log.debug("Removing signal handler for dead frontend")
-                self.signals_handlers.remove(handler)
+                self.signals_handlers.remove(wrapper)
 
     def _bridgeDeactivateSignals(self):
         if hasattr(self, "signals_paused"):