comparison piecrust/environment.py @ 47:558e3602be40

Cache rendered segments to disk.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 22 Aug 2014 12:25:35 -0700
parents 43091c9837bf
children fce061f8c2ed
comparison
equal deleted inserted replaced
46:99dea56238af 47:558e3602be40
1 import re
1 import time 2 import time
3 import json
2 import logging 4 import logging
3 import threading 5 import threading
4 import repoze.lru 6 import repoze.lru
5 7
6 8
7 logger = logging.getLogger(__name__) 9 logger = logging.getLogger(__name__)
8 10
9 11
12 re_fs_cache_key = re.compile(r'[^\d\w\-\._]+')
13
14
15 def _make_fs_cache_key(key):
16 return re_fs_cache_key.sub('_', key)
17
18
10 class MemCache(object): 19 class MemCache(object):
20 """ Simple memory cache. It can be backed by a simple file-system
21 cache, but items need to be JSON-serializable to do this.
22 """
11 def __init__(self, size=2048): 23 def __init__(self, size=2048):
12 self.cache = repoze.lru.LRUCache(size) 24 self.cache = repoze.lru.LRUCache(size)
13 self.lock = threading.RLock() 25 self.lock = threading.RLock()
26 self.fs_cache = None
14 27
15 def get(self, key, item_maker): 28 def get(self, key, item_maker):
16 item = self.cache.get(key) 29 item = self.cache.get(key)
17 if item is None: 30 if item is None:
18 logger.debug("Acquiring lock for: %s" % key) 31 logger.debug("Acquiring lock for: %s" % key)
19 with self.lock: 32 with self.lock:
20 item = self.cache.get(key) 33 item = self.cache.get(key)
21 if item is None: 34 if item is None:
35 if self.fs_cache is not None:
36 # Try first from the file-system cache.
37 fs_key = _make_fs_cache_key(key)
38 logger.debug("'%s' not found in cache, trying the "
39 "file-system: %s" % (key, fs_key))
40 try:
41 item_raw = self.fs_cache.read(fs_key)
42 item = json.loads(item_raw)
43 self.cache.put(key, item)
44 return item
45 except:
46 pass
47
48 # Look into the mem-cache.
22 logger.debug("'%s' not found in cache, must build." % key) 49 logger.debug("'%s' not found in cache, must build." % key)
23 item = item_maker() 50 item = item_maker()
24 self.cache.put(key, item) 51 self.cache.put(key, item)
52
53 # Save to the file-system if needed.
54 if self.fs_cache is not None:
55 item_raw = json.dumps(item)
56 self.fs_cache.write(fs_key, item_raw)
25 return item 57 return item
26 58
27 59
28 PHASE_PAGE_PARSING = 0 60 PHASE_PAGE_PARSING = 0
29 PHASE_PAGE_FORMATTING = 1 61 PHASE_PAGE_FORMATTING = 1
74 self.page_repository = MemCache() 106 self.page_repository = MemCache()
75 self.rendered_segments_repository = MemCache() 107 self.rendered_segments_repository = MemCache()
76 self.base_asset_url_format = '%uri%' 108 self.base_asset_url_format = '%uri%'
77 109
78 def initialize(self, app): 110 def initialize(self, app):
79 pass 111 cache = app.cache.getCache('renders')
112 self.rendered_segments_repository.fs_cache = cache
80 113
81 114
82 class StandardEnvironment(Environment): 115 class StandardEnvironment(Environment):
83 def __init__(self): 116 def __init__(self):
84 super(StandardEnvironment, self).__init__() 117 super(StandardEnvironment, self).__init__()