2011-03-27 2 views
5

J'ai un ReconnectingClientFactory dans un module. J'aimerais que le module soit aussi flexible que possible. Je n'ai besoin que d'une seule connexion TCP. J'utilise l'usine en tant qu'interface persistante pour cette connexion. Dans le passé, l'usine répondait aux déconnexions en réessayant sans cesse la connexion, n'informant jamais le script de niveau supérieur (le script qui importe le module) qu'il y avait des problèmes de connexion.Comment concevoir une usine torsadée pour gérer les déconnexions?

Voici un bref exemple de ce que j'ai:

Factory(protocol.ReconnectingClientFactory): 

    def clientConnectionFailed(self, connector, reason): 
     ... 

    def clientConnectionLost(self, connector, reason): 
     ... 

Je pense qu'il est préférable que j'informerai le script de haut niveau (le script qui importe le module) quand il y a des problèmes de connexion. De cette façon, le script de niveau supérieur peut définir un comportement de résolution de déconnexion plutôt que d'être codé en dur dans le module. Mais quelle est la meilleure façon de communiquer les problèmes de connexion au script de niveau supérieur?

Je pourrais déclencher une exception, mais où serait-elle attrapée? Je suppose que le réacteur l'attraperait, mais en quoi cela aide-t-il?

Il n'y a pas de callbacks ou de erreurs que je peux déclencher pour informer le script du problème de connexion.

Le script supérieur peut fournir des fonctions spécifiques [en tant qu'arguments] à appeler lorsque des problèmes de connexion se produisent. Est-ce que c'est un bon design?

Répondre

3

Cette question est un peu trop abstraite pour fournir une réponse directe. Cela dépend de ce que fait votre module de haut niveau. Cependant, vous devriez envisager d'utiliser endpoints plutôt que ClientFactory. Cela pourrait répondre à certaines de vos questions de conception. Recevoir des notifications de connexion perdues est un peu plus compliqué (puisque ClientFactory.clientConnectionLost est en fait une notification en double de IProtocol.connectionLost, il n'existe plus dans l'API des points de terminaison, donc vous devez envelopper l'objet IProtocol si vous vous en souciez) mais cela vous permet d'utiliser plus générique mécanismes pour réessayer échoué connexions, au lieu de clientConnectionFailed, vous obtenez simplement un errback sur le Deferred que vous avez de retour de connect. Ainsi, par exemple, si tout ce que vous vouliez faire était de « garder reconnectant jusqu'à ce que vous réussissiez », vous pouvez utiliser ce totalement générique Deferred -retry boucle au lieu de quelque chose de spécifique aux connexions comme ReconnectingClientFactory:

# Warning, untested, sorry if it's broken. 
@inlineCallbacks 
def retry(deferredThing, delay=30.0, retryCount=5): 
    retries = retryCount 
    while True: 
     try: 
      result = yield deferredThing() 
     except: 
      if not retries: 
       raise 
      retries -= 1 
      log.err() 
      yield deferLater(reactor, delay, lambda : None) 
     else: 
      returnValue(result) 

De même, si vous pourriez faire que la fonction deferredThing renvoie un Deferred qui se déclencherait uniquement lorsque la logique d'application de votre protocole serait terminée, en plus d'appeler IStreamServerEndpoint.connect, surveillé pour connectionLost et échouerait si la connexion était perdue avant que la logique intéressante ne soit terminée.

Deferreds peut être un moyen efficace de gérer ce type d'état de réessai asynchrone sur plusieurs niveaux d'un système.

+1

Cela semble être une solution incomplète, car elle donne seulement un moyen de gérer les tentatives de connexion échouées, pas les connexions perdues. Comment gérez-vous les connexions perdues sans la coopération du protocole? –

Questions connexes