From a9b18580f824953ccc45ccc441840e0b09132549 Mon Sep 17 00:00:00 2001 From: Scott Ferguson Date: Thu, 19 May 2016 07:27:29 -0400 Subject: [PATCH 1/3] issue_120_add_pool_close - attempt to politely close connections --- happybase/pool.py | 27 +++++++++++++++++++++++++++ tests/test_api.py | 11 +++++++++++ 2 files changed, 38 insertions(+) diff --git a/happybase/pool.py b/happybase/pool.py index aa0da99..0f41a3b 100644 --- a/happybase/pool.py +++ b/happybase/pool.py @@ -90,6 +90,33 @@ def _return_connection(self, connection): """Return a connection to the pool.""" self._queue.put(connection) + def close_connections(self, timeout=None): + """ + Attempts to politely close all connections in the pool. + Waits for used connections to become available or until the + timeout is exceeded. + + :param int timeout: number of seconds to wait for a connection to + become available (optional) + :return: None + """ + if timeout: + if not isinstance(timeout, int): + raise TypeError("close_connections 'timeout' arg must be an integer") + + if not timeout > 0: + raise ValueError("close_connections 'timeout' arg must be greater than zero") + + while not self._queue.empty(): + try: + conn = self._queue.get(block=True, timeout=timeout) + conn.close() + conn = None + except Queue.Empty: + raise NoConnectionsAvailable( + "Closing connections failed: No connection available from " + "pool within specified timeout of {}".format(timeout)) + @contextlib.contextmanager def connection(self, timeout=None): """ diff --git a/tests/test_api.py b/tests/test_api.py index cbfdbd0..3b6913f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -556,6 +556,17 @@ def run(): t.start() t.join() +def test_pool_close(): + pool = ConnectionPool(size=3, **connection_kwargs) + + with pool.connection(): + with assert_raises(TypeError): + pool.close_connections(timeout='foo') + + with assert_raises(ValueError): + pool.close_connections(timeout=0) + + pool.close_connections() if __name__ == '__main__': import logging From a943d75a6aadbb151e749a56eda3827c2d97bedd Mon Sep 17 00:00:00 2001 From: Scott Ferguson Date: Thu, 19 May 2016 08:35:07 -0400 Subject: [PATCH 2/3] issue_120_add_pool_close - update test, 0 doesn't pass 'if' condition. --- tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index 3b6913f..c3e4f23 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -564,7 +564,7 @@ def test_pool_close(): pool.close_connections(timeout='foo') with assert_raises(ValueError): - pool.close_connections(timeout=0) + pool.close_connections(timeout=-1) pool.close_connections() From 12785603b48035b34b1e5b473ad314f04c7fe6cc Mon Sep 17 00:00:00 2001 From: Scott Ferguson Date: Sat, 21 May 2016 10:05:43 -0400 Subject: [PATCH 3/3] issue_120_add_pool_close - fixup None check --- happybase/pool.py | 2 +- tests/test_api.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/happybase/pool.py b/happybase/pool.py index 0f41a3b..5ec4e04 100644 --- a/happybase/pool.py +++ b/happybase/pool.py @@ -100,7 +100,7 @@ def close_connections(self, timeout=None): become available (optional) :return: None """ - if timeout: + if timeout is not None: if not isinstance(timeout, int): raise TypeError("close_connections 'timeout' arg must be an integer") diff --git a/tests/test_api.py b/tests/test_api.py index c3e4f23..3b6913f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -564,7 +564,7 @@ def test_pool_close(): pool.close_connections(timeout='foo') with assert_raises(ValueError): - pool.close_connections(timeout=-1) + pool.close_connections(timeout=0) pool.close_connections()