Happybase Connection Pooling
Wrote a simple connection pool for Happybase using socketpool.
import time
import random
import contextlib
import happybase
from socketpool import ConnectionPool
from socketpool.conn import TcpConnector
class HappybaseConnectionPool(object):
''' singleton to share a connection pool per process '''
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(HappybaseConnectionPool, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self, host, **options):
options['host'] = host
if not hasattr(self, 'pool'):
self.pool = ConnectionPool(
factory=HappybaseConnector,
max_size=options.get('max_size', 10),
options=options,
)
def connection(self, **options):
return self.pool.connection(**options)
@contextlib.contextmanager
def table(self, table_name):
with self.pool.connection() as connector:
yield connector.table(table_name)
class HappybaseConnector(TcpConnector):
def __init__(self, host, port, pool=None, **kwargs):
self.host = host
self.port = port
self.connection = happybase.Connection(self.host, self.port)
self._connected = True
# use a 'jiggle' value to make sure there is some
# randomization to expiry, to avoid many conns expiring very
# closely together.
self._life = time.time() - random.randint(0, 10)
self._pool = pool
self.logging = kwargs.get('logging')
def is_connected(self):
if self._connected and self.connection.transport.isOpen():
try:
# isOpen is unreliable, actually try to do something
self.connection.tables()
return True
except:
pass
return False
def handle_exception(self, exception):
if self.logging:
self.logging.error(exception)
else:
print exception
def invalidate(self):
self.connection.close()
self._connected = False
self._life = -1
def open(self):
pass
def close(self):
self.release()
def __getattr__(self, name):
if name in ['table', 'tables', 'create_table', 'delete_table',
'enable_table', 'disable_table', 'is_table_enabled', 'compact_table']:
return getattr(self.connection, name)
else:
raise AttributeError(name)
You can get a single pool object from anywhere in your stack with the following:
pool = HappybaseConnectionPool('localhost', '9090')
with pool.connection() as connection:
connection.create_table('foobar')
Note: happybase may be adding their own connection pool shortly.