from functools import wraps from django core cache import cache from c

 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
from functools import wraps
from django.core.cache import cache
from cPickle import loads, dumps
INVALIDATORS = []
def make_cache_key(prop, id):
if prop.startswith('calculate_'):
prop = prop[10:]
return 'city:%s:%s' % (prop, id)
def serialize(rich):
return dumps(rich)
def deserialize(flat):
return loads(flat)
def _get_signal_by_name(signal_name):
import gamecore.signals
return getattr(gamecore.signals, signal_name)
def resolve_signals(signals):
from django.dispatch import Signal
resolved = []
for signal in signals:
if isinstance(signal, basestring):
resolved.append(_get_signal_by_name(signal))
elif isinstance(signal, Signal):
resolved.append(signal)
return resolved
def cache_city(*args):
signals = resolve_signals(args)
def decor(func):
prop = func.__name__
connect_invalidators(prop, signals)
@wraps(func)
def wrapper(slf, city):
key = make_cache_key(prop, city.pk)
flatten = cache.get(key)
if flatten is None:
value = func(slf, city)
cache.set(key, serialize(value))
else:
value = deserialize(flatten)
return value
return wrapper
return decor
def make_cache_invalidator(prop):
def invalidate(signal, sender, *args, **kwargs):
event = sender
key = make_cache_key(prop, event.city_id)
cache.delete(key)
return invalidate
def connect_invalidators(prop, signals):
if (prop, signals) not in INVALIDATORS:
INVALIDATORS.append((prop, signals))
for signal in signals:
invalidator = make_cache_invalidator(prop)
signal.connect(invalidator, weak=False)
def invalidate(city, prop):
key = make_cache_key(prop, city.pk)
cache.delete(key)