Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConnectionError for deferreds waiting for connection #89

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

jakm
Copy link
Contributor

@jakm jakm commented Sep 21, 2015

Call errback with ConnectionError of deferreds waiting for connection
in ConnectionHandler's wrapper when all attempts for connecting fail.

Call errback with ConnectionError of deferreds waiting for connection
in ConnectionHandler's wrapper when all attempts for connecting fail.
@fiorix
Copy link
Collaborator

fiorix commented Sep 21, 2015

Haven't tested this code but I'm not too sure about it. The concern is about a reconnection attempt calling errback more than once, and failing.

@jakm
Copy link
Contributor Author

jakm commented Sep 21, 2015

I thing calling errback more than once won't happen because RedisFactory.deferred is set to None after errback and is called only when there is no connection in pool. Because there is 1:1 relation between RedisFactory and ConnectionHandler (I haven't found another case) there is no other way to call factory's errback when connection fail. In ConnectionHandler, deferred is put to waiting set only when factory's deferred has called == False.

@fiorix
Copy link
Collaborator

fiorix commented Sep 21, 2015

Good, will let this sit for another day to see if anyone else has concerns, otherwise will merge in.

@jakm
Copy link
Contributor Author

jakm commented Sep 21, 2015

Here is example script that explain (I hope) what I expect from this patch.

#!/usr/bin/env python

import sys

from twisted.internet import defer, reactor, task
from twisted.python import log

from txredisapi import lazyConnectionPool

pool = None


def newPool():
    global pool
    pool = lazyConnectionPool('localhost', 6379, connectTimeout=1, poolsize=2)
    log.msg('New pool: %s' % pool)
    pool._factory.maxRetries = 5


def reconnectPool(res, delay):
    global pool

    log.msg('Connection failed after %s attempts: %s' % (pool._factory.retries - 1, res.getErrorMessage()))
    log.msg('Will create new pool after %s seconds' % delay)

    reactor.callLater(delay, newPool)


def doWork(batch_id):
    global pool

    @defer.inlineCallbacks
    def ping(task_id):
        try:
            yield pool.ping()
        except Exception as e:
            log.msg('Ping #%s.%s: %s %s' % (batch_id, task_id, type(e), str(e)))

    log.msg('Running doWork batch #%s' % batch_id)

    defers = []
    for i in range(10):
        d = ping(i)
        defers.append(d)

    return defer.DeferredList(defers)


@defer.inlineCallbacks
def test():
    global pool

    reconnectDelay = 10

    try:
        newPool()

        pool._connected.addErrback(reconnectPool, reconnectDelay)

        yield doWork(0)
        yield doWork(1)

        yield task.deferLater(reactor, reconnectDelay + 1, lambda: None)

        yield doWork(2)
        yield doWork(3)

    except Exception as e:
        print type(e), str(e)
    finally:
        reactor.stop()

log.startLogging(sys.stdout)

reactor.suggestThreadPoolSize(1)
reactor.callWhenRunning(test)
reactor.run()

And its result:

2015-09-21 16:14:04+0200 [-] Log opened.
2015-09-21 16:14:04+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:04+0200 [-] New pool: <Redis Connection: Not connected>
2015-09-21 16:14:04+0200 [-] Running doWork batch #0
2015-09-21 16:14:04+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23db48> will retry in 2 seconds
2015-09-21 16:14:04+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23de60> will retry in 7 seconds
2015-09-21 16:14:04+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:07+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:07+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23db48> will retry in 10 seconds
2015-09-21 16:14:07+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:12+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:12+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23de60> will retry in 9 seconds
2015-09-21 16:14:12+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:18+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:18+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23db48> will retry in 11 seconds
2015-09-21 16:14:18+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:22+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:22+0200 [Uninitialized] Abandoning <twisted.internet.tcp.Connector instance at 0x7f80de23de60> after 6 retries.
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.6: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.3: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.0: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.7: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.4: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.9: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.8: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.1: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.5: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #0.2: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Running doWork batch #1
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.0: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.1: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.2: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.3: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.4: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.5: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.6: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.7: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.8: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Ping #1.9: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:22+0200 [Uninitialized] Connection failed after 5 attempts: Connection was refused by other side: 111: Connection refused.
2015-09-21 16:14:22+0200 [Uninitialized] Will create new pool after 10 seconds
2015-09-21 16:14:22+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:29+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:29+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d950>
2015-09-21 16:14:32+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:32+0200 [-] New pool: <Redis Connection: Not connected>
2015-09-21 16:14:32+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23d710> will retry in 2 seconds
2015-09-21 16:14:32+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80dddc4ea8> will retry in 5 seconds
2015-09-21 16:14:32+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:33+0200 [-] Running doWork batch #2
2015-09-21 16:14:35+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:35+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23d710> will retry in 12 seconds
2015-09-21 16:14:35+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:37+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:37+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80dddc4ea8> will retry in 10 seconds
2015-09-21 16:14:37+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:47+0200 [-] Starting factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:47+0200 [Uninitialized] <twisted.internet.tcp.Connector instance at 0x7f80de23d710> will retry in 10 seconds
2015-09-21 16:14:47+0200 [Uninitialized] Abandoning <twisted.internet.tcp.Connector instance at 0x7f80dddc4ea8> after 6 retries.
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.2: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.0: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.8: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.5: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.9: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.7: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.3: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.4: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.1: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #2.6: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Running doWork batch #3
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.0: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.1: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.2: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.3: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.4: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.5: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.6: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.7: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.8: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Ping #3.9: <class 'txredisapi.ConnectionError'> Not connected
2015-09-21 16:14:47+0200 [Uninitialized] Stopping factory <txredisapi.RedisFactory instance at 0x7f80de23d6c8>
2015-09-21 16:14:47+0200 [-] Main loop terminated.

Batch 0 failed because of new code and batch 1 because pool is not connected (and don't try connect). Then I create new pool and run batchs 2 and 3, their behaviour is same as 0 and 1.

I've fixed cancelWaiting because it discarded the failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants