Search code examples
pythontwistedautobahnwamp-protocol

How to send Autobahn/Twisted WAMP message from outside of protocol?


I am following the basic wamp pubsub examples in the github code:

This example publishes messages from within the class:

class Component(ApplicationSession):
   """
An application component that publishes an event every second.
"""

   def __init__(self, realm = "realm1"):
      ApplicationSession.__init__(self)
      self._realm = realm


   def onConnect(self):
      self.join(self._realm)


   @inlineCallbacks
   def onJoin(self, details):
      counter = 0
      while True:
         self.publish('com.myapp.topic1', counter)
         counter += 1
         yield sleep(1)

I want to create a reference so that I can publish messages over this connection from elsewhere in the code, i.e. myobject.myconnection.publish('com.myapp.topic1', 'My message')

From this similar question the answer seems to be that upon connection, I need to set something like self.factory.myconnection = self. I have tried multiple permutations of this without success.

The factory setup portion is below:

   ## create a WAMP application session factory
   ##
   from autobahn.twisted.wamp import ApplicationSessionFactory
   session_factory = ApplicationSessionFactory()


   ## .. and set the session class on the factory
   ##
   session_factory.session = Component


   ## create a WAMP-over-WebSocket transport client factory
   ##
   from autobahn.twisted.websocket import WampWebSocketClientFactory
   transport_factory = WampWebSocketClientFactory(session_factory, args.wsurl, debug = args.debug)
   transport_factory.setProtocolOptions(failByDrop = False)


   ## start a WebSocket client from an endpoint
   ##
   client = clientFromString(reactor, args.websocket)
   client.connect(transport_factory)

Where would any reference that I set from within the class be attached? to client? to transport_factory? to session_factory?


Solution

  • Upon your app session joining the WAMP realm, it sets a reference to itself on the app session factory:

    class MyAppComponent(ApplicationSession):
    
       ... snip
    
       def onJoin(self, details):
          if not self.factory._myAppSession:
             self.factory._myAppSession = self
    

    You then can access this session from elsewhere in your code, e.g.

       @inlineCallbacks
       def pub():
          counter = 0  
          while True:
             ## here we can access the app session that was created ..
             ##
             if session_factory._myAppSession:
                session_factory._myAppSession.publish('com.myapp.topic123', counter)
                print("published event", counter)
             else:
                print("no session")
             counter += 1
             yield sleep(1)
    
       pub()