1 from datetime import datetime, timedelta
2 import hashlib
3
4 from pyperry.relation import Relation
5
7
9 self.default_interval = timedelta(seconds=interval)
10 self.store = {}
11
12 - def read(self, key):
13 if self.store.has_key(key):
14 if self.store[key][1] > datetime.now():
15 return self.store[key][0]
16 else:
17 del self.store[key]
18
19 - def write(self, key, val, expire_at=None):
20 self.clear()
21 self.store[key] = (val,
22 expire_at or (datetime.now() + self.default_interval))
23
24 - def clear(self, key=None):
25 if key:
26 del self.store[key]
27 else:
28 now = datetime.now()
29 for key in self.store.keys():
30 if self.store[key][1] < now:
31 del self.store[key]
32
34 del self.store
35 self.store = {}
36
37
39 """ LocalCache middleware
40
41 Caches results of queries in memory returning the previous result of
42 repeated queries until the entry expires. Entries are cached based on
43 the query used.
44
45 Config options:
46 - interval: The interval in seconds that a given cache entry will be
47 considered fresh
48 - max_entry_size: Max len of results that will be cached. If set only
49 results less than this value will be stored in the cache. All others
50 will be refetched every time.
51
52 Importing this module adds the fresh query option to Relation. This allows
53 the developer to easily force a query to be fresh::
54
55 # This query will always fetch fresh data
56 Person.where({ 'name': 'bob' }).fresh()
57
58 """
59
60 cache_store = CacheStore(300)
61
63 if not options:
64 options = {}
65 self.next = next
66 self.options = options
67
69 rel = kwargs['relation']
70 key = hashlib.sha1("%s--%s" % (rel.klass, rel.query())).hexdigest()
71
72 result = self.cache_store.read(key)
73
74 if not result or rel.params['fresh']:
75
76 result = self.next(**kwargs)
77
78
79 expires_at = None
80 if self.options.has_key('interval'):
81 expires_at = (datetime.now() +
82 timedelta(seconds=self.options.get('interval')))
83
84
85 if (not self.options.has_key('max_entry_size') or
86 self.options['max_entry_size'] > len(result)):
87 self.cache_store.write(key, result, expires_at)
88
89 return result
90
91 cache_store = LocalCache.cache_store
92
93
94
95
96 if not Relation.singular_query_methods.count('fresh'):
97 Relation.singular_query_methods.append('fresh')
98
99 - def fresh(self, value=True):
100 self = self.clone()
101 self.params['fresh'] = value
102 self._query = None
103 self._records = None
104 return self
105
106 setattr(Relation, 'fresh', fresh)
107