comparison piecrust/environment.py @ 96:0445a2232de7

Improvements and fixes to incremental baking. * Better handling of the render pass during page rendering. * Used sources are paired with the pass they were used in. * Proper use and invalidation of the rendered segments cache based on render passes. * The `Assetor` is also better tracking what was used in a page. * Add flags on a page to get better caching information for the debug window. * Property invalidation of the previous bake record when needed. * Better information about why pages are delayed.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 07 Sep 2014 23:48:57 -0700
parents 563ce5dd02af
children 208c652551a3
comparison
equal deleted inserted replaced
95:cb6eadea0845 96:0445a2232de7
23 """ 23 """
24 def __init__(self, size=2048): 24 def __init__(self, size=2048):
25 self.cache = repoze.lru.LRUCache(size) 25 self.cache = repoze.lru.LRUCache(size)
26 self.lock = threading.RLock() 26 self.lock = threading.RLock()
27 self.fs_cache = None 27 self.fs_cache = None
28 self._invalidated_fs_items = set()
29
30 def invalidate(self, key):
31 with self.lock:
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)
28 38
29 def get(self, key, item_maker, fs_cache_time=None): 39 def get(self, key, item_maker, fs_cache_time=None):
30 item = self.cache.get(key) 40 item = self.cache.get(key)
31 if item is None: 41 if item is None:
32 logger.debug("Acquiring lock for: %s" % key) 42 logger.debug("Acquiring lock for: %s" % key)
35 if item is None: 45 if item is None:
36 if (self.fs_cache is not None and 46 if (self.fs_cache is not None and
37 fs_cache_time is not None): 47 fs_cache_time is not None):
38 # Try first from the file-system cache. 48 # Try first from the file-system cache.
39 fs_key = _make_fs_cache_key(key) 49 fs_key = _make_fs_cache_key(key)
40 if self.fs_cache.isValid(fs_key, fs_cache_time): 50 if (fs_key not in self._invalidated_fs_items and
51 self.fs_cache.isValid(fs_key, fs_cache_time)):
41 logger.debug("'%s' found in file-system cache." % 52 logger.debug("'%s' found in file-system cache." %
42 key) 53 key)
43 item_raw = self.fs_cache.read(fs_key) 54 item_raw = self.fs_cache.read(fs_key)
44 item = json.loads(item_raw, 55 item = json.loads(item_raw,
45 object_pairs_hook=collections.OrderedDict) 56 object_pairs_hook=collections.OrderedDict)
57 item_raw = json.dumps(item) 68 item_raw = json.dumps(item)
58 self.fs_cache.write(fs_key, item_raw) 69 self.fs_cache.write(fs_key, item_raw)
59 return item 70 return item
60 71
61 72
62 PHASE_PAGE_PARSING = 0
63 PHASE_PAGE_FORMATTING = 1
64 PHASE_PAGE_RENDERING = 2
65
66
67 class ExecutionInfo(object): 73 class ExecutionInfo(object):
68 def __init__(self, page, phase, render_ctx): 74 def __init__(self, page, render_ctx):
69 self.page = page 75 self.page = page
70 self.phase = phase
71 self.render_ctx = render_ctx 76 self.render_ctx = render_ctx
72 self.was_cache_valid = False 77 self.was_cache_valid = False
73 self.start_time = time.clock() 78 self.start_time = time.clock()
74 79
75 80
91 for ei in self._page_stack: 96 for ei in self._page_stack:
92 if ei.page == page: 97 if ei.page == page:
93 return True 98 return True
94 return False 99 return False
95 100
96 def pushPage(self, page, phase, render_ctx): 101 def pushPage(self, page, render_ctx):
97 self._page_stack.append(ExecutionInfo(page, phase, render_ctx)) 102 if len(self._page_stack) > 0:
103 top = self._page_stack[-1]
104 assert top.page is not page
105 self._page_stack.append(ExecutionInfo(page, render_ctx))
98 106
99 def popPage(self): 107 def popPage(self):
100 del self._page_stack[-1] 108 del self._page_stack[-1]
101 109
102 110
106 self.exec_info_stack = ExecutionInfoStack() 114 self.exec_info_stack = ExecutionInfoStack()
107 self.was_cache_cleaned = False 115 self.was_cache_cleaned = False
108 self.page_repository = MemCache() 116 self.page_repository = MemCache()
109 self.rendered_segments_repository = MemCache() 117 self.rendered_segments_repository = MemCache()
110 self.base_asset_url_format = '%uri%' 118 self.base_asset_url_format = '%uri%'
111 self._use_rendered_segments_fs_cache = False
112 119
113 def initialize(self, app): 120 def initialize(self, app):
114 if self._use_rendered_segments_fs_cache: 121 cache = app.cache.getCache('renders')
115 cache = app.cache.getCache('renders') 122 self.rendered_segments_repository.fs_cache = cache
116 self.rendered_segments_repository.fs_cache = cache
117 123
118 124
119 class StandardEnvironment(Environment): 125 class StandardEnvironment(Environment):
120 def __init__(self): 126 def __init__(self):
121 super(StandardEnvironment, self).__init__() 127 super(StandardEnvironment, self).__init__()