Mercurial > piecrust2
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 = [] |