2011-03-27 9 views
5

Tengo un ReconnectingClientFactory en un módulo. Me gustaría que el módulo sea lo más flexible posible. Solo necesito una conexión TCP única. Utilizo la fábrica como una interfaz persistente para esta conexión. En el pasado, la fábrica respondía a las desconexiones reintentando sin cesar la conexión, nunca informando al script de nivel superior (el script que importa el módulo) que había problemas de conexión.¿Cómo diseño una fábrica retorcida para manejar desconexiones?

He aquí un breve ejemplo de lo que tengo:

Factory(protocol.ReconnectingClientFactory): 

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

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

Creo que es mejor si se informo al archivo de nivel superior (el script que importa el módulo) cuando hay problemas de conexión. De esta manera, la secuencia de comandos de nivel superior puede definir el comportamiento de resolución de desconexión en lugar de que esté codificado en el módulo. Pero, ¿cuál es la mejor manera de comunicar los problemas de conexión al script de nivel superior?

Podría presentar una excepción, pero ¿dónde se detectaría? Supongo que el reactor podría atraparlo, pero ¿cómo ayuda eso?

No hay devoluciones de llamada o errores que pueda disparar para informar al script superior del problema de conexión.

La secuencia de comandos superior podría proporcionar funciones específicas [como argumentos] para llamar cuando se producen problemas de conexión. Sin embargo, este es un buen diseño?

Respuesta

3

Esta pregunta es demasiado abstracta para proporcionar una respuesta directa. Depende de lo que esté haciendo su módulo de nivel superior. Sin embargo, debe considerar usar endpoints, en lugar de ClientFactory. Esto podría abordar algunas de sus preguntas de diseño. Recibir notificaciones de pérdida de conexión es un poco complicado (ya que ClientFactory.clientConnectionLost es en realidad una notificación duplicada de IProtocol.connectionLost, ya no existe en la API de puntos finales, por lo que debe ajustar el objeto IProtocol si así lo desea), pero le permite utilizar mecanismos para reintentar conexiones fallidas, ya que en lugar de clientConnectionFailed, simplemente obtiene un error en el Deferred que obtuvo de connect. Así, por ejemplo, si todo lo que quería hacer era "mantener a volver a conectar hasta que tenga éxito", podría utilizar esta totalmente genérico Deferred -retry bucle en lugar de algo específico a las conexiones como 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) 

mismo modo, si podría hacer que la función deferredThing devuelva un Deferred que se activaría solo cuando se completó la lógica de aplicación de su protocolo, además de llamar al IStreamServerEndpoint.connect, se observó connectionLost y fallaría si la conexión se perdía antes de que se completara la lógica interesante.

Deferreds puede ser una forma efectiva de administrar este tipo de estado de reintentos asincrónico en múltiples niveles de un sistema.

+1

Esto parece ser una solución incompleta, ya que solo proporciona una forma de manejar intentos fallidos de conexión, conexiones no perdidas. ¿Cómo se manejan las conexiones perdidas sin cooperación del protocolo? –

Cuestiones relacionadas