Search code examples
pythonconnectionqueuestomp

python - reconnect stomp connection when dead


As per the documentation, given that I've instantiated a connection:

>>> import stomp
>>> c = stomp.Connection([('127.0.0.1', 62615)])
>>> c.start()
>>> c.connect('admin', 'password', wait=True)

How do I monitor it so that it reconnects on c.is_connected == False?

>>> reconnect_on_dead_connection(c)
...
>>> [1479749503] reconnected dead connection

Solution

  • You can wrap your connection and check if its connected every call.

    import stomp
    
    
    def reconnect(connection):
        """reconnect here"""
    
    
    class ReconnectWrapper(object):
        def __init__(self, connection):
            self.__connection = connection
    
        def __getattr__(self, item):
            if not self.__connection.is_connected:
                reconnect(self.__connection)
            return getattr(self.__connection, item)
    
    
    if __name__ == '__main__':
        c = stomp.Connection([('127.0.0.1', 62615)])
        c.start()
        c.connect('admin', 'password', wait=True)
        magic_connection = ReconnectWrapper(c)
    

    Test:

    from scratch_35 import ReconnectWrapper
    import unittest
    import mock
    
    
    class TestReconnection(unittest.TestCase):
    
        def setUp(self):
            self.connection = mock.MagicMock()
            self.reconnect_patcher = mock.patch("scratch_35.reconnect")
            self.reconnect = self.reconnect_patcher.start()
    
        def tearDown(self):
            self.reconnect_patcher.stop()
    
        def test_pass_call_to_warapped_connection(self):
            connection = ReconnectWrapper(self.connection)
            connection.send("abc")
            self.reconnect.assert_not_called()
            self.connection.send.assert_called_once_with("abc")
    
        def test_reconnect_when_disconnected(self):
            self.connection.is_connected = False
            connection = ReconnectWrapper(self.connection)
            connection.send("abc")
            self.reconnect.assert_called_once_with(self.connection)
            self.connection.send.assert_called_once_with("abc")
    
    
    if __name__ == '__main__':
        unittest.main()
    

    result:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.004s
    
    OK
    

    The key is magic method __getatter__ it's called everytime you try to access an attribute that is not provided by an object. More about method __getattr__ you can find in doucmentation https://docs.python.org/2/reference/datamodel.html#object.getattr .