comparison piecrust/environment.py @ 416:ff6cc43fb40c

internal: Move `MemCache` to the `cache` module, remove threading locks.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 20 Jun 2015 21:05:25 -0700
parents a1567766c83c
children eef887cec776
comparison
equal deleted inserted replaced
415:0e9a94b7fdfa 416:ff6cc43fb40c
1 import time 1 import time
2 import json
3 import logging 2 import logging
4 import hashlib
5 import contextlib 3 import contextlib
6 import collections 4 from piecrust.cache import MemCache
7 import repoze.lru
8 5
9 6
10 logger = logging.getLogger(__name__) 7 logger = logging.getLogger(__name__)
11
12
13 def _make_fs_cache_key(key):
14 return hashlib.md5(key.encode('utf8')).hexdigest()
15
16
17 class MemCache(object):
18 """ Simple memory cache. It can be backed by a simple file-system
19 cache, but items need to be JSON-serializable to do this.
20 """
21 def __init__(self, size=2048):
22 self.cache = repoze.lru.LRUCache(size)
23 self.fs_cache = None
24 self._last_access_hit = None
25 self._invalidated_fs_items = set()
26
27 @property
28 def last_access_hit(self):
29 return self._last_access_hit
30
31 def invalidate(self, key):
32 logger.debug("Invalidating cache item '%s'." % key)
33 self.cache.invalidate(key)
34 if self.fs_cache:
35 logger.debug("Invalidating FS cache item '%s'." % key)
36 fs_key = _make_fs_cache_key(key)
37 self._invalidated_fs_items.add(fs_key)
38
39 def put(self, key, item, save_to_fs=True):
40 self.cache.put(key, item)
41 if self.fs_cache and save_to_fs:
42 fs_key = _make_fs_cache_key(key)
43 item_raw = json.dumps(item)
44 self.fs_cache.write(fs_key, item_raw)
45
46 def get(self, key, item_maker, fs_cache_time=None, save_to_fs=True):
47 self._last_access_hit = True
48 item = self.cache.get(key)
49 if item is None:
50 if (self.fs_cache is not None and
51 fs_cache_time is not None):
52 # Try first from the file-system cache.
53 fs_key = _make_fs_cache_key(key)
54 if (fs_key not in self._invalidated_fs_items and
55 self.fs_cache.isValid(fs_key, fs_cache_time)):
56 logger.debug("'%s' found in file-system cache." %
57 key)
58 item_raw = self.fs_cache.read(fs_key)
59 item = json.loads(
60 item_raw,
61 object_pairs_hook=collections.OrderedDict)
62 self.cache.put(key, item)
63 return item
64
65 # Look into the mem-cache.
66 logger.debug("'%s' not found in cache, must build." % key)
67 item = item_maker()
68 self.cache.put(key, item)
69 self._last_access_hit = False
70
71 # Save to the file-system if needed.
72 if self.fs_cache is not None and save_to_fs:
73 item_raw = json.dumps(item)
74 self.fs_cache.write(fs_key, item_raw)
75
76 return item
77 8
78 9
79 class ExecutionInfo(object): 10 class ExecutionInfo(object):
80 def __init__(self, page, render_ctx): 11 def __init__(self, page, render_ctx):
81 self.page = page 12 self.page = page
82 self.render_ctx = render_ctx 13 self.render_ctx = render_ctx
83 self.was_cache_valid = False 14 self.was_cache_valid = False
84 self.start_time = time.clock() 15 self.start_time = time.perf_counter()
85 16
86 17
87 class ExecutionInfoStack(object): 18 class ExecutionInfoStack(object):
88 def __init__(self): 19 def __init__(self):
89 self._page_stack = [] 20 self._page_stack = []