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