-
Notifications
You must be signed in to change notification settings - Fork 0
/
factories.py
117 lines (92 loc) · 3.23 KB
/
factories.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
.. module:: decorators
:platform: Unix, Windows, Linux
:synopsis: Decorators for simpler work with cache
.. :moduleauthor: Michal Domanski <mdomans@gmail.com>
"""
import functools
from tools import make_key, make_group_value
class CacheDecorator(object):
"""
Decorator for work with multiple groups for each key
cached = cached_factory(cache_client)
@cached
def something():
return 1
or
@cached(timeout=10)
def something():
return 1
@cached(timeout=10, jitter=True)
def something():
return 1
supports every possible cache client
"""
group_keys = []
def __call__(self, key=None, group_keys=None, group_key=None):
def decorate_func(fn):
@functools.wraps(fn)
def decorates_args(*args, **kwargs):
self.key = key
self.group_keys = group_keys or []
if group_key:
self.group_keys.append(group_key)
result = self.run_decorated(fn, *args, **kwargs)
return result
return decorates_args
return decorate_func
def __init__(self, cache_client):
self.cache = cache_client
self.key = ''
def expire_key(self, key):
self.cache.set(make_key(key), None)
def run_decorated(self, func, *args, **kwargs):
if self.key:
key = make_key(self.key)
else:
key = make_key(repr(func), repr(args), repr(kwargs))
group_keys = map(make_key, self.group_keys)
cache = self.cache
value = None
evaluate = False
if group_keys:
data = cache.get_multi(group_keys + [key])
data_dict = data.get(key)
if (not data) or (not data_dict):
evaluate = True
if data_dict:
value = data_dict['value']
for group_key in group_keys:
if group_key not in data or group_key not in data_dict or data[group_key] != data_dict[group_key]:
evaluate = True
if group_key in data and not data[group_key]:
del data[group_key]
evaluate = True
else:
value = cache.get(key)
if not value:
evaluate = True
if isinstance(value, dict) and 'is_multigroup' in value:
evaluate = True
if evaluate:
value = func(*args, **kwargs)
if not group_keys:
cache.set(key, value)
else:
group_dict = {}
for group_key in group_keys:
if group_key not in data:
group_dict[group_key] = make_group_value(group_key)
else:
group_dict[group_key] = data[group_key]
data_dict = {}
data_dict['value'] = value
data_dict['is_multigroup'] = True
data_dict.update(group_dict)
group_dict[key] = data_dict
cache.set_multi(group_dict)
return value
def cached_factory(client):
return CacheDecorator(client)