Source code for biothings.utils.redis

import logging
import random

try:
    import redis
except ImportError:
    logging.error('"redis" module is required to access Redis server.')


[docs] class RedisClientError(Exception): pass
[docs] class RedisClient(object): client = None
[docs] @classmethod def get_client(cls, params): if cls.client is None: cls.client = cls(params) return cls.client
def __init__(self, connection_params): self._mapdb = None self.connection_params = connection_params @property def mapdb(self): if self._mapdb is None: self._mapdb = redis.StrictRedis(db=0, **self.connection_params) return self._mapdb
[docs] def get_db(self, db_name=None): """ Return a redict client instance from a database name or database number (if db_name is an integer) """ self.check() try: db_num = int(db_name) except ValueError: db_num = self.mapdb.get(db_name) if not db_num: db_num = self.pick_db() self.mapdb.set(db_name, int(db_num)) return redis.StrictRedis(db=int(db_num), **self.connection_params)
[docs] def pick_db(self): """ Return a database number, preferably not used (db doesn't exist). If no database available (all are used), will be one and flush it... """ db_max_num = int(self.mapdb.config_get("databases")["databases"] or 16) # -1: we always keep db=0 (meta db) avail = dict(zip(range(1, db_max_num), [True] * (db_max_num - 1))) for info in self.mapdb.info("keyspace"): if not info.startswith("db"): continue num = int(info.replace("db", "")) if num == 0: continue avail.pop(num) if not avail: db_num = random.randint(1, db_max_num - 1) else: db_num = random.choice(list(avail.keys())) return db_num
[docs] def check(self): if not self.mapdb.get("__META__") == b"0": raise RedisClientError("Can't find database metadata, you may want to use initialize()")
[docs] def initialize(self, deep=False): """ Careful: this may delete data. Prepare Redis instance to work with biothings hub: - database 0: this db is used to store a mapping between database index and database name (so a database can be accessed by name). This method will flush this db and prepare it. - any other databases will be flushed if deep is True, making the redis server fully dedicated to """ if deep: self.mapdb.flushall() self.mapdb.flushdb() self.mapdb.set("__META__", 0) self.check()