Mercurial > piecrust2
diff piecrust/serving/server.py @ 552:9612cfc6455a
serve: Rewrite of the Server-Sent Event code for build notifications.
At the moment the server monitors the asset directories, and notifies the
browser when an asset has changed and has been re-processed.
* Fix issues around long-running requests/threads which mess up the ability
to shutdown the server correctly with `CTRL-C` (see comments in code).
* Move the notification queue to each SSE producer, to support having multiple
pages open in a browser.
* Add JS/CSS for showing quick notifications about re-processed assets.
* Add support for hot-reloading CSS and pictures that have been re-processed.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 08 Aug 2015 16:12:04 -0700 |
parents | f2b875ecc940 |
children | cc6f3dbe3048 |
line wrap: on
line diff
--- a/piecrust/serving/server.py Sat Aug 08 15:55:24 2015 -0700 +++ b/piecrust/serving/server.py Sat Aug 08 16:12:04 2015 -0700 @@ -110,13 +110,19 @@ def _run_request(self, environ, start_response): try: - return self._try_run_request(environ, start_response) + response = self._try_run_request(environ) + if isinstance(response, tuple): + response, close_func = response + return ClosingIterator(response(environ, start_response), + [close_func]) + else: + return response(environ, start_response) except Exception as ex: if self.debug: raise return self._handle_error(ex, environ, start_response) - def _try_run_request(self, environ, start_response): + def _try_run_request(self, environ): request = Request(environ) # We don't support anything else than GET requests since we're @@ -129,12 +135,12 @@ # Handle special requests right away. response = self._try_special_request(environ, request) if response is not None: - return response(environ, start_response) + return response # Also handle requests to a pipeline-built asset right away. response = self._try_serve_asset(environ, request) if response is not None: - return response(environ, start_response) + return response # Create the app for this request. app = PieCrust(root_dir=self.root_dir, debug=self.debug) @@ -153,12 +159,12 @@ # Let's see if it can be a page asset. response = self._try_serve_page_asset(app, environ, request) if response is not None: - return response(environ, start_response) + return response # Nope. Let's see if it's an actual page. try: response = self._try_serve_page(app, environ, request) - return response(environ, start_response) + return response except (RouteNotFoundError, SourceNotFoundError) as ex: raise NotFound() from ex except HTTPException: @@ -187,19 +193,24 @@ debug_mount = '/__piecrust_debug/' if request.path.startswith(debug_mount): rel_req_path = request.path[len(debug_mount):] + if rel_req_path == 'werkzeug_shutdown': + shutdown_func = environ.get('werkzeug.server.shutdown') + if shutdown_func is None: + raise RuntimeError('Not running with the Werkzeug Server') + shutdown_func() + return Response("Server shutting down...") + if rel_req_path == 'pipeline_status': from piecrust.serving.procloop import ( - PipelineStatusServerSideEventProducer) - provider = PipelineStatusServerSideEventProducer( - self._proc_loop.status_queue) - it = ClosingIterator(provider.run(), [provider.close]) - response = Response(it) + PipelineStatusServerSentEventProducer) + provider = PipelineStatusServerSentEventProducer( + self._proc_loop) + it = provider.run() + response = Response(it, mimetype='text/event-stream') response.headers['Cache-Control'] = 'no-cache' - if 'text/event-stream' in request.accept_mimetypes: - response.mimetype = 'text/event-stream' - response.direct_passthrough = True - response.implicit_sequence_conversion = False - return response + response.headers['Last-Event-ID'] = \ + self._proc_loop.last_status_id + return response, provider.close return None