Changeset 169:bb939a909750


Ignore:
Timestamp:
Feb 25, 2012, 8:27:56 PM (9 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Message:

Let wokkel.component.Component reconnect if first attempt fails.

Author: ralphm.
Fixes #75.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • NEWS

    r167 r169  
     1x.x.x (yyyy-mm-dd)
     2==================
     3
     4Fixes
     5-----
     6
     7 - wokkel.component.Component now reconnects if first attempt failed (#75).
     8
     9
    1100.7.0 (2012-01-23)
    2 ======================
    3 
    4 Features
    5 --------
     11==================
     12
     13Features
     14--------
     15
    616 - Added method wokkel.data_form.Form.typeCheck for type checking incoming Data
    717   Forms submissions against field definitions.
  • wokkel/component.py

    r166 r169  
    55
    66"""
    7 XMPP External Component utilities
     7XMPP External Component utilities.
    88"""
    99
     
    2121
    2222class Component(StreamManager, service.Service):
     23    """
     24    XMPP External Component service.
     25
     26    This service is a XMPP stream manager that connects as an External
     27    Component to an XMPP server, as described in
     28    U{XEP-0114<http://xmpp.org/extensions/xep-0114.html>}.
     29    """
    2330    def __init__(self, host, port, jid, password):
    2431        self.host = host
     
    2936        StreamManager.__init__(self, factory)
    3037
     38
    3139    def _authd(self, xs):
     40        """
     41        Called when stream initialization has completed.
     42
     43        This replaces the C{send} method of the C{XmlStream} instance
     44        that represents the current connection so that outgoing stanzas
     45        always have a from attribute set to the JID of the component.
     46        """
    3247        old_send = xs.send
    3348
     
    4156        StreamManager._authd(self, xs)
    4257
     58
    4359    def initializationFailed(self, reason):
    4460        """
     
    5167        reason.raiseException()
    5268
     69
    5370    def startService(self):
     71        """
     72        Start the service and connect to the server.
     73        """
    5474        service.Service.startService(self)
    5575
     76        self._connection = self._getConnection()
     77
     78
     79    def stopService(self):
     80        """
     81        Stop the service, close the connection and prevent reconnects.
     82        """
     83        service.Service.stopService(self)
     84
    5685        self.factory.stopTrying()
    57         self._connection = self._getConnection()
    58 
    59     def stopService(self):
    60         service.Service.stopService(self)
    61 
    6286        self._connection.disconnect()
    6387
     88
    6489    def _getConnection(self):
     90        """
     91        Create a connector that connects to the server.
     92        """
    6593        return reactor.connectTCP(self.host, self.port, self.factory)
    6694
  • wokkel/test/test_component.py

    r165 r169  
    33
    44"""
    5 Tests for L{wokkel.component}
     5Tests for L{wokkel.component}.
    66"""
    77
    88from zope.interface.verify import verifyObject
    99
     10from twisted.internet.base import BaseConnector
     11from twisted.internet.error import ConnectionRefusedError
     12from twisted.internet.task import Clock
    1013from twisted.python import failure
    1114from twisted.trial import unittest
     
    1821from wokkel import component
    1922from wokkel.generic import XmlPipe
     23
     24class FakeConnector(BaseConnector):
     25    """
     26    Fake connector that counts connection attempts.
     27    """
     28    connects = 0
     29
     30    def connect(self):
     31        self.connects += 1
     32        BaseConnector.connect(self)
     33
     34
     35    def _makeTransport(self):
     36        return None
     37
     38
     39
     40class TestableComponent(component.Component):
     41    """
     42    Testable component.
     43
     44    This component provides the created factory with a L{Clock}
     45    instead of the regular reactor and uses L{FakeConnector} for testing
     46    connects and reconnects.
     47    """
     48
     49    def __init__(self, *args, **kwargs):
     50        component.Component.__init__(self, *args, **kwargs)
     51        self.factory.clock = Clock()
     52
     53
     54    def _getConnection(self):
     55        c = FakeConnector(self.factory, None, None)
     56        c.connect()
     57        return c
     58
     59
     60
     61class ComponentTest(unittest.TestCase):
     62    """
     63    Tests for L{component.Component}.
     64    """
     65    def test_startServiceReconnectAfterFailure(self):
     66        """
     67        When the first connection attempt fails, retry.
     68        """
     69        comp = TestableComponent('example.org', 5347,
     70                                 'test.example.org', 'secret')
     71
     72        # Starting the service initiates a connection attempt.
     73        comp.startService()
     74        connector = comp._connection
     75        self.assertEqual(1, connector.connects)
     76
     77        # Fail the connection.
     78        connector.connectionFailed(ConnectionRefusedError())
     79
     80        # After a back-off delay, a new connection is attempted.
     81        comp.factory.clock.advance(5)
     82        self.assertEqual(2, connector.connects)
     83
     84
     85    def test_stopServiceNoReconnect(self):
     86        """
     87        When the service is stopped, no reconnect is attempted.
     88        """
     89        comp = TestableComponent('example.org', 5347,
     90                                 'test.example.org', 'secret')
     91
     92        # Starting the service initiates a connection attempt.
     93        comp.startService()
     94        connector = comp._connection
     95
     96        # Fail the connection.
     97        connector.connectionFailed(ConnectionRefusedError())
     98
     99        # If the service is stopped before the back-off delay expires,
     100        # no new connection is attempted.
     101        comp.factory.clock.advance(1)
     102        comp.stopService()
     103        comp.factory.clock.advance(4)
     104        self.assertEqual(1, connector.connects)
     105
     106
    20107
    21108class InternalComponentTest(unittest.TestCase):
Note: See TracChangeset for help on using the changeset viewer.