Beispiel #1
0
from time import sleep
from expiring_dict import ExpiringDict

cache = ExpiringDict()  # No TTL set, keys set via [] will not expire

cache["abc"] = "persistent"
cache.ttl("123", "expires", 1)  # This will expire after 1 second
print("abc" in cache)
print("123" in cache)
sleep(1.1)
print("abc" in cache)
print("123" not in cache)

cache2 = ExpiringDict(1)

cache2["abc"] = "expires"
cache2["123"] = "also expires"
print("abc" in cache2)
print("123" in cache2)
sleep(1.1)
print("abc" not in cache2)
print("123" not in cache2)
Beispiel #2
0
def test_set_ttl():
    d = ExpiringDict(interval=0.005)
    d.ttl("key", "expire", 0.01)
    assert len(d) == 1
    sleep(0.02)
    assert len(d) == 0
def test_set_ttl():
    d = ExpiringDict()
    d.ttl("key", "expire", 1)
    assert len(d) == 1
    sleep(1.1)
    assert len(d) == 0
class Server(object):
    def __init__(self, host=None, port=None, max_clients=None):
        if not host:
            host = os.getenv('HOST', '0.0.0.0')
        if not port:
            port = os.getenv('PORT', 31337)
        if not max_clients:
            max_clients = os.getenv('MAX_CLIENTS', 15)
        self._pool = Pool(int(max_clients))
        self._server = StreamServer((host, int(port)),
                                    self.connection_handler,
                                    spawn=self._pool)

        self._protocol = DataHandler()
        self._kv = ExpiringDict()

        self._commands = self.get_commands()

    def get_commands(self):
        return {
            'GET': self.get,
            'SET': self.set,
            'DEL': self.delete,
            'KEYS': self.keys,
            'FLUSHDB': self.flush,
            'EXPIRE': self.expire,
            'HGET': self.hget,
            'HSET': self.hset,
            'LSET': self.lset,
            'RPUSH': self.rpush,
            'LPUSH': self.lpush,
            'LRANGE': self.lrange,
            'LINDEX': self.lindex
        }

    def connection_handler(self, conn, address):
        logger.info('Connection received: %s:%s' % address)
        socket_file = conn.makefile('rwb')

        while True:
            try:
                data = self._protocol.handle_request(socket_file)
            except Disconnect:
                logger.info('Client went away: %s:%s' % address)
                break
            try:
                resp = self.get_response(data)
            except CommandError as exc:
                logger.exception('Command error')
                resp = Error(exc.args[0])

            self._protocol.write_response(socket_file, resp)

    def run(self):
        self._server.serve_forever()

    def get_response(self, data):
        if not isinstance(data, list):
            try:
                data = data.split()
            except:
                raise CommandError('Request must be list or simple string.')

        if not data:
            raise CommandError('Missing command')

        command = data[0].upper()
        if command not in self._commands:
            raise CommandError('Unrecognized command: %s' % command)
        else:
            logger.debug('Received %s', command)
        try:
            response = self._commands[command](*data[1:])
        except TypeError:
            raise CommandError(
                f'ERR wrong number of arguments for {command.lower()} command')
        return response

    def get(self, key):
        return self._kv.get(key)

    def set(self, key, value):
        self._kv[key] = value
        return '1'

    def delete(self, key):
        if key in self._kv:
            del self._kv[key]
            return 1
        return 0

    def keys(self, pattern):
        r = []
        if pattern == '*':
            pattern = '\w*'
        for k in self._kv.keys():
            if re.match(pattern, k):
                r.append(k)
        return r

    def flush(self):
        kvlen = len(self._kv)
        self._kv.clear()
        return str(kvlen)

    def expire(self, key, ttl):
        value = self._kv.get(key, None)
        if value:
            del self._kv[key]
            self._kv.ttl(key, value, float(ttl))
            return 1
        return 0

    def hset(self, key, field, value):
        self._kv.setdefault(key, {})
        self._kv[key][field] = value
        return 1

    def hget(self, k, field):
        if self._kv.get(k):
            return self._kv[k].get(field)

    def lset(self, key, index, value):
        self._kv.setdefault(key, [])
        self._kv[key][int(index)] = value
        return 'OK'

    def rpush(self, key, *value):
        self._kv.setdefault(key, [])
        for v in value:
            self._kv[key].append(v)
        return len(self._kv[key])

    def lpush(self, key, *value):
        self._kv.setdefault(key, [])
        for v in value:
            self._kv[key].insert(0, v)
        return len(self._kv[key])

    def lrange(self, key, start, end):
        if isinstance(self._kv.get(key), list):
            if end == '-1':
                return self._kv[key][int(start):]
            return self._kv[key][int(start):int(end) + 1]
        return None

    def lindex(self, key, index):
        if isinstance(self._kv.get(key), list):
            try:
                return self._kv[key][int(index)]
            except IndexError:
                return None
        return None