我在模块中有一个ReconnectingClientFactory。我希望模块尽可能灵活。我只需要一个TCP连接。我使用工厂作为此连接的持久接口。在过去,工厂会通过无休止地重试连接来响应断开连接,从不通知顶级脚本(导入模块的脚本)存在连接问题。
以下是我所拥有的一个简短示例:
Factory(protocol.ReconnectingClientFactory):
def clientConnectionFailed(self, connector, reason):
...
def clientConnectionLost(self, connector, reason):
...
我认为最好是在出现连接问题时通知顶级脚本(导入模块的脚本)。这样,顶级脚本可以定义断开连接解析行为,而不是在模块中对其进行硬编码。但是,将连接问题传达给顶级脚本的最佳方法是什么?
我可以提出异常,但它会被捕获到哪里?我想反应堆会抓住它,但这有什么帮助呢?
我无法触发回调或错误,以通知顶级脚本连接问题。
顶级脚本可以提供在发生连接问题时要调用的特定函数[作为参数]。这是一个好的设计吗?
答案 0 :(得分:3)
这个问题有点过于抽象,无法提供直接的答案。这取决于您的顶级模块正在做什么。
但是,您应该考虑使用endpoints,而不是ClientFactory
。这可能会解决您的一些设计问题。接收连接丢失通知是一个小问题(因为ClientFactory.clientConnectionLost
实际上是IProtocol.connectionLost
的重复通知,它在端点API中不再存在;所以如果你必须包装IProtocol
对象关心这一点)但它确实让你使用更通用的机制来重试失败的连接,而不是clientConnectionFailed
而不是Deferred
你得到的错误来自connect
。因此,举例来说,如果你想做的就是“在你成功之前保持重新连接”,你可以使用这个完全通用的Deferred
- 重试循环,而不是像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)
同样,如果你可以使deferredThing
函数返回Deferred
,只有当你的协议的应用程序逻辑完成时才会触发它,除了调用IStreamServerEndpoint.connect
之外,还要注意{{1}如果在有趣的逻辑完成之前连接丢失,则会失败。
connectionLost
可以是在系统的多个级别上管理此类异步重试状态的有效方法。