changeset 455:cb3446be44b7

bake: Abort "render first" jobs if we start using other pages. This prevents the baker from having one worker stuck on a very long job, like rendering the index page of a blog with lots and lots of posts.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 08 Jul 2015 22:51:29 -0700
parents 96d363e2da4b
children 5e902e228053
files piecrust/baking/worker.py piecrust/data/iterators.py piecrust/environment.py
diffstat 3 files changed, 22 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/baking/worker.py	Mon Jul 06 21:32:40 2015 -0700
+++ b/piecrust/baking/worker.py	Wed Jul 08 22:51:29 2015 -0700
@@ -3,6 +3,7 @@
 from piecrust.app import PieCrust
 from piecrust.baking.records import BakeRecord, _get_transition_key
 from piecrust.baking.single import PageBaker, BakingError
+from piecrust.environment import AbortedSourceUseError
 from piecrust.rendering import (
         QualifiedPage, PageRenderingContext, render_page_segments)
 from piecrust.routing import create_route_metadata
@@ -147,18 +148,25 @@
         route_metadata = create_route_metadata(page)
         qp = QualifiedPage(page, route, route_metadata)
         ctx = PageRenderingContext(qp)
+        self.app.env.abort_source_use = True
 
         result = {
                 'path': fac.path,
+                'aborted': False,
                 'errors': None}
         logger.debug("Preparing page: %s" % fac.ref_spec)
         try:
             render_page_segments(ctx)
+        except AbortedSourceUseError:
+            logger.debug("Page %s was aborted." % fac.ref_spec)
+            result['aborted'] = True
         except Exception as ex:
             logger.debug("Got rendering error. Sending it to master.")
             result['errors'] = _get_errors(ex)
             if self.ctx.debug:
                 logger.exception(ex)
+        finally:
+            self.app.env.abort_source_use = False
         return result
 
 
--- a/piecrust/data/iterators.py	Mon Jul 06 21:32:40 2015 -0700
+++ b/piecrust/data/iterators.py	Wed Jul 08 22:51:29 2015 -0700
@@ -1,6 +1,8 @@
 import logging
 from piecrust.data.filters import PaginationFilter
+from piecrust.environment import AbortedSourceUseError
 from piecrust.events import Event
+from piecrust.sources.base import PageSource
 from piecrust.sources.interfaces import IPaginationSource
 
 
@@ -289,6 +291,13 @@
         if self._pagesData is not None:
             return
 
+        if (self._current_page is not None and
+                self._current_page.app.env.abort_source_use and
+                isinstance(self._source, PageSource)):
+            logger.debug("Aborting iteration from %s." %
+                         self._current_page.ref_spec)
+            raise AbortedSourceUseError()
+
         self._ensureSorter()
 
         it_chain = self._pages
--- a/piecrust/environment.py	Mon Jul 06 21:32:40 2015 -0700
+++ b/piecrust/environment.py	Wed Jul 08 22:51:29 2015 -0700
@@ -7,6 +7,10 @@
 logger = logging.getLogger(__name__)
 
 
+class AbortedSourceUseError(Exception):
+    pass
+
+
 class ExecutionInfo(object):
     def __init__(self, page, render_ctx):
         self.page = page
@@ -60,6 +64,7 @@
         self.fs_caches = {
                 'renders': self.rendered_segments_repository}
         self.fs_cache_only_for_main_page = False
+        self.abort_source_use = False
         self._default_layout_extensions = None
         self._timers = {}