class CacheModule:
    def __init__(self, name, max_size=128, from_remote=None):
        '''
		:param max_size:	最大容量
		:param from_remote: 查询数据函数,返回值必须是一个dict
		:param ttl:	有效时间,单位:秒
		'''
        self.local_cache = LRU(max_size=max_size)
        self.from_remote = from_remote
        self.empty = {}
        self.name = name

    def get_all(self, keys: list) -> dict:
        result, missing_keys = {}, []

        for key in keys:
            val = self.local_cache.get(key)
            if val is not None:
                if val != self.empty:
                    result[key] = val
            else:
                missing_keys.append(key)
        # 缓存未命中
        if len(missing_keys) > 0:
            missing_dict = self.reload(missing_keys)
            result = {**result, **missing_dict}

        return result

    def remove(self, keys: list):
        for key in keys:
            self.local_cache.__delitem__(key)

    def statistics(self):
        hitRateAsString = '%.3f' % (
            self.local_cache.hit_count /
            (self.local_cache.hit_count + self.local_cache.miss_count))
        return {
            "name": self.name,
            "hit_count": self.local_cache.hit_count,
            "miss_count": self.local_cache.miss_count,
            "size": len(self.local_cache.keys()),
            "hitRateAsString": hitRateAsString + "%",
        }

    def reload(self, keys: list) -> dict:
        d = {}
        missing_vals = self.from_remote(keys)
        # 不存在的值,设置为空
        if missing_vals:
            for key, val in missing_vals.items():
                self.local_cache.setdefault(key, val)
                d[key] = val
        for missing_key in keys:
            self.local_cache.setdefault(missing_key, self.empty)
        return d
Exemplo n.º 2
0
def test_lru():
    lru = LRU(max_size=1)
    lru['hi'] = 0
    lru['bye'] = 1
    assert len(lru) == 1
    lru['bye']
    assert lru.get('hi') is None

    del lru['bye']
    assert 'bye' not in lru
    assert len(lru) == 0
    assert not lru
class CacheModule:
    def __init__(self, max_size: int, ttl_millis: int, from_remote):
        '''
		:param max_size: max_size of the cache,using LRU
		:param ttl_millis: max live time for the objects
		:param from_remote: function to load data if the key not exists
		'''
        self.cache = LRU(max_size=max_size)
        self.ttl = ttl_millis
        self.from_remote = from_remote
        self._lock = RLock()

    def multi_get(self, keys) -> dict:
        result, missing = {}, []

        now = int(round(time.time() * 1000))
        for key in keys:
            value: dict = self.cache.get(key)
            # key未命中
            if not value:
                missing.append(key)
            # key超时
            elif now < value['max_time']:
                missing.append(key)
            # key存在且不是默认值
            elif value['data']:
                result[key] = value['data']

        if len(missing) > 0:
            loads_d: dict = self.from_remote(missing)
            dft = {
                'max_time': int(round(time.time() * 1000)) + self.ttl,
                'data': {}
            }
            for key in missing:
                loads_d.setdefault(key, dft)
            self.multi_set(loads_d)
        return result

    def multi_set(self, data: dict):
        with self._lock:
            for k, v in data.items():
                self.cache.setdefault(k, v)

    def remove(self, keys):
        with self._lock:
            for key in keys:
                self.cache.pop(key)
Exemplo n.º 4
0
def test_lru_basic():
    lru = LRU(max_size=1)
    repr(lru)  # sanity

    lru['hi'] = 0
    lru['bye'] = 1
    assert len(lru) == 1
    lru['bye']
    assert lru.get('hi') is None

    del lru['bye']
    assert 'bye' not in lru
    assert len(lru) == 0
    assert not lru

    try:
        lru.pop('bye')
    except KeyError:
        pass
    else:
        assert False

    default = object()
    assert lru.pop('bye', default) is default

    try:
        lru.popitem()
    except KeyError:
        pass
    else:
        assert False

    lru['another'] = 1
    assert lru.popitem() == ('another', 1)

    lru['yet_another'] = 2
    assert lru.pop('yet_another') == 2

    lru['yet_another'] = 3
    assert lru.pop('yet_another', default) == 3

    lru['yet_another'] = 4
    lru.clear()
    assert not lru

    lru['yet_another'] = 5
    second_lru = LRU(max_size=1)
    assert lru.copy() == lru

    second_lru['yet_another'] = 5
    assert second_lru == lru
    assert lru == second_lru

    lru.update(LRU(max_size=2, values=[('a', 1), ('b', 2)]))
    assert len(lru) == 1
    assert 'yet_another' not in lru

    lru.setdefault('x', 2)
    assert dict(lru) == {'x': 2}
    lru.setdefault('x', 3)
    assert dict(lru) == {'x': 2}

    assert lru != second_lru
    assert second_lru != lru
Exemplo n.º 5
0
def test_lru_basic():
    lru = LRU(max_size=1)
    repr(lru)                   # sanity

    lru['hi'] = 0
    lru['bye'] = 1
    assert len(lru) == 1
    lru['bye']
    assert lru.get('hi') is None

    del lru['bye']
    assert 'bye' not in lru
    assert len(lru) == 0
    assert not lru

    try:
        lru.pop('bye')
    except KeyError:
        pass
    else:
        assert False

    default = object()
    assert lru.pop('bye', default) is default

    try:
        lru.popitem()
    except KeyError:
        pass
    else:
        assert False

    lru['another'] = 1
    assert lru.popitem() == ('another', 1)

    lru['yet_another'] = 2
    assert lru.pop('yet_another') == 2

    lru['yet_another'] = 3
    assert lru.pop('yet_another', default) == 3

    lru['yet_another'] = 4
    lru.clear()
    assert not lru

    lru['yet_another'] = 5
    second_lru = LRU(max_size=1)
    assert lru.copy() == lru

    second_lru['yet_another'] = 5
    assert second_lru == lru
    assert lru == second_lru

    lru.update(LRU(max_size=2, values=[('a', 1),
                                       ('b', 2)]))
    assert len(lru) == 1
    assert 'yet_another' not in lru

    lru.setdefault('x', 2)
    assert dict(lru) == {'x': 2}
    lru.setdefault('x', 3)
    assert dict(lru) == {'x': 2}

    assert lru != second_lru
    assert second_lru != lru