Я реализую библиотечный модуль, который будет служить клиентом для уведомлений об изменениях в couchdb.Я хочу, чтобы библиотека находилась в «непрерывном» режиме, то есть соединение должно оставаться открытым всегда, или, по крайней мере, оно должно быть повторно подключено, если соединение было закрыто, чтобы у couchdb был канал для уведомления о любых новых изменениях, происходящих вбаза данных.Затем я обработаю эти уведомления для генерации определенных событий (это еще не реализовано).
Подход, который я выбрал, состоит в том, чтобы использовать ReconnectingClientFactory (которая выполняет автоматическое повторное соединение согласно разработанному алгоритму) в качестве основыдля моего протокола Factory.Всякий раз, когда соединение установлено, вызывается метод buildProtocol.В этом методе я создаю экземпляр протокола и запускаю callLater (немедленно), чтобы сообщить, что соединение готово.В функции cdConnected я отправляю запрос и добавляю обратный вызов для обработки полученных данных (cbReceived).
Код выполняет переподключение, как и ожидалось, но у меня возникли две разные проблемы:
- запрос не выполняется (данные не передаются по TCP-соединению), но я не знаю, почему.
- генерируется ошибка, даже если соединение закрыто чисто.
Может быть, у кого-то есть представление о том, что я делаю неправильно?
Спасибо!
(редактировать: ошибка «Соединение было закрыто чисто». Печатается самостоятельно, поэтому это может бытьигнорируется)
Вот код:
from twisted.internet import defer
from twisted.internet.protocol import ReconnectingClientFactory
from twisted.web._newclient import HTTP11ClientProtocol
from twisted.web._newclient import Request
from twisted.web.client import _parse
class MyReconnectingClientFactory(ReconnectingClientFactory):
def __init__(self, reactor, cbConnected):
self.reactor = reactor
self.cbConnected = cbConnected
def startedConnecting(self, connector):
print 'Started to connect ...'
def buildProtocol(self, addr):
print 'Resetting reconnection delay'
self.resetDelay()
proto = HTTP11ClientProtocol()
self.reactor.callLater(0, self.cbConnected, proto)
return proto
def clientConnectionLost(self, connector, reason):
print 'Lost connection. Reason:', reason
ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
def clientConnectionFailed(self, connector, reason):
print 'Connection failed. Reason:', reason
ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
def cbReceived(response):
print response
def printError(failure):
print "printError > %s" % (str(failure))
def cbConnected(proto):
print "Sending request ..."
req = Request(method, path, headers, bodyProducer)
d = proto.request(req)
d.addCallback(cbReceived).addErrback(printError)
return d
from twisted.internet import reactor
uri='http://localhost:5984/cn/_changes?feed=continuous'
method='GET'
headers=None
bodyProducer=None
scheme, host, port, path = _parse(uri)
factory = MyReconnectingClientFactory(reactor, cbConnected)
reactor.connectTCP(host, port, factory)
reactor.run()
А вот вывод:
Started to connect ...
Resetting reconnection delay
Sending request ...
printError > [Failure instance: Traceback (failure with no frames): <class 'twisted.web._newclient.RequestGenerationFailed'>: [<twisted.python.failure.Failure <type 'exceptions.AttributeError'>>]
]
Lost connection. Reason: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
Started to connect ...
Resetting reconnection delay
Sending request ...
printError > [Failure instance: Traceback (failure with no frames): <class 'twisted.web._newclient.RequestGenerationFailed'>: [<twisted.python.failure.Failure <type 'exceptions.AttributeError'>>]
]
Lost connection. Reason: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]