Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6324883
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T16:47:19+00:00 2026-05-24T16:47:19+00:00

I am implementing a library module to serve as client for couchdb change notifications.

  • 0

I am implementing a library module to serve as client for couchdb change notifications. I want to have the library in “continuous” mode, that is, the connection must remain open forever, or at least it must reconnect if the connection has been closed, so that couchdb has a channel to notify of any new changes happening in the database. I will then process those notifications to generate certain events (this is not yet implemented).

The approach that I have chosen is to use the ReconnectingClientFactory (which does automatic re-connection as per an elaborated algorithm) as basis for my Protocol Factory. Whenever the connection has been established, the buildProtocol method is called. In this method I create the protocol instance, and fire a callLater (immediately) to signal that the connection is ready. In the cdConnected function, I send the request and add a callback to process the received data (cbReceived).

The code does reconnection as expected, but I am having two different problems:

  • the request is failing (no data is sent over the tcp connection), but I do not know why.
  • an error is generated, even though the connection is closed cleanly.

Maybe somebody has an idea of what I am doing wrong?

Thanks!

(edit: the “Connection was closed cleanly.” error is being printed by myself, so it can be ignored)

Here is the code:

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()

And here is the output:

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.
]
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T16:47:19+00:00Added an answer on May 24, 2026 at 4:47 pm

    You should take a look at the failures generated. _newclient has a habit of throwing compound failures; these contain further failures.

    I adapted your code a little:

    def printError(failure):
    print "printError > %r" % failure
    
    from twisted.web import _newclient
    if failure.check(_newclient.RequestGenerationFailed):
        print "printError: RequestGenerationFailed"
        for f in failure.value.reasons:
            print "printError > %r" % f
            print f.getTraceback()
    

    You were doing a str() on failure and that’s not a good way to get information about an exception. Let repr take care of it, that’s its job.

    Using %r, I saw that it was actually giving me a RequestGenerationFailed. That’s a more interesting failure. The failure value has reasons.

    With my modification, the script gave this:

    Started to connect ...
    Resetting reconnection delay
    Sending request ...
    printError > <twisted.python.failure.Failure <class 'twisted.web._newclient.RequestGenerationFailed'>>
    printError: RequestGenerationFailed
    printError > <twisted.python.failure.Failure <type 'exceptions.AttributeError'>>
    Traceback (most recent call last):
      File "/usr/lib64/python2.7/site-packages/twisted/internet/base.py", line 1174, in mainLoop
        self.runUntilCurrent()
      File "/usr/lib64/python2.7/site-packages/twisted/internet/base.py", line 796, in runUntilCurrent
        call.func(*call.args, **call.kw)
      File "so.py", line 50, in cbConnected
        d = proto.request(req)
      File "/usr/lib64/python2.7/site-packages/twisted/web/_newclient.py", line 1266, in request
        _requestDeferred = maybeDeferred(request.writeTo, self.transport)
    --- <exception caught here> ---
      File "/usr/lib64/python2.7/site-packages/twisted/internet/defer.py", line 125, in maybeDeferred
        result = f(*args, **kw)
      File "/usr/lib64/python2.7/site-packages/twisted/web/_newclient.py", line 703, in writeTo
        self._writeHeaders(transport, None)
      File "/usr/lib64/python2.7/site-packages/twisted/web/_newclient.py", line 535, in _writeHeaders
        hosts = self.headers.getRawHeaders('host', ())
    exceptions.AttributeError: 'NoneType' object has no attribute 'getRawHeaders'
    
    Lost connection.  Reason: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
    

    That should give you a good clue on where to look for your actual problem.

    Incidentally, take a look at Paisley, a Twisted client for CouchDB: paisley

    There are a few branches, and in particular my changes branch has some change notification stuff you may be interested in. I made a desktop applet that showed me tasks added to my CouchDB-based todo system.

    It sounds like your changes are a) already in there or b) should go in there; and c) you should consider working with and contributing to Paisley.

    Good luck!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am implementing a memcached client library. I want it to support several servers
I'm currently implementing a JavaScript library that keeps track of the history of changes
I have been tasked with implementing a PKI library in C# for a company
I'm implementing a cache in a class library that i'm using in an asp.net
I have been using Python's pickle module for implementing a thin file-based persistence layer.
I am implementing a client library for a private HTTP-API using python requests .
I'm currently looking for a hand drawing (2D) library/module (that would be like Paint,
I'm implementing a C++/CLI class library that does some low-level device-related stuff and exposes
I am implementing a WCF service library. You add a new code file that
I have c++ library that need communicate with Python plugged in modules. Communication supposes

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.