Source code for biothings.utils.redis

import random
import logging

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


[docs]class RedisClientError(Exception): pass
class RedisClient(object): client = None @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 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) 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 def check(self): if not self.mapdb.get("__META__") == b'0': raise RedisClientError("Can't find database metadata, you may want to use initialize()") 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()