annotate piecrust/serving/wrappers.py @ 860:c71472e6537f

refactor: Get the processing loop in the server functional again.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 08 Jun 2017 08:51:27 -0700
parents 4850f8c21b6e
children 1bb0d973dc69
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
1 import os
558
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
2 import signal
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
3 import logging
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
4
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
5
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
6 logger = logging.getLogger(__name__)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
7
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
8
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
9 def run_werkzeug_server(appfactory, host, port,
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
10 use_debugger=False, use_reloader=False):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
11 from werkzeug.serving import run_simple
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
12
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
13 def _run_sse_check():
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
14 # We don't want to run the processing loop here if this isn't
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
15 # the actual process that does the serving. In most cases it is,
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
16 # but if we're using Werkzeug's reloader, then it won't be the
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
17 # first time we get there... it will only be the correct process
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
18 # the second time, when the reloading process is spawned, with the
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
19 # `WERKZEUG_RUN_MAIN` variable set.
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
20 return (not use_reloader or
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
21 os.environ.get('WERKZEUG_RUN_MAIN') == 'true')
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
22
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
23 app = _get_piecrust_server(appfactory,
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
24 run_sse_check=_run_sse_check)
552
9612cfc6455a serve: Rewrite of the Server-Sent Event code for build notifications.
Ludovic Chabant <ludovic@chabant.com>
parents: 374
diff changeset
25
558
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
26 # We need to do a few things to get Werkzeug to properly shutdown or
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
27 # restart while SSE responses are running. This is because Werkzeug runs
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
28 # them in background threads (because we tell it to), but those threads
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
29 # are not marked as "daemon", so when the main thread tries to exit, it
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
30 # will wait on those SSE responses to end, which will pretty much never
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
31 # happen (except for a timeout or the user closing their browser).
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
32 #
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
33 # In theory we should be using a proper async server for this kind of
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
34 # stuff, but I'd rather avoid additional dependencies on stuff that's not
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
35 # necessarily super portable.
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
36 #
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
37 # Anyway, we run the server as usual, but we intercept the `SIGINT`
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
38 # signal for when the user presses `CTRL-C`. When that happens, we set a
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
39 # flag that will make all existing SSE loops return, which will make it
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
40 # possible for the main thread to end too.
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
41 #
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
42 # We also need to do a few thing for the "reloading" feature in Werkzeug,
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
43 # see the comment down there for more info.
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
44 def _shutdown_server():
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
45 from piecrust.serving import procloop
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
46 procloop.server_shutdown = True
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
47
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
48 def _shutdown_server_and_raise_sigint():
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
49 if not use_reloader or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
50 # We only need to shutdown the SSE requests for the process
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
51 # that actually runs them.
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
52 print("")
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
53 print("Shutting server down...")
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
54 _shutdown_server()
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
55 raise KeyboardInterrupt()
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
56
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
57 signal.signal(signal.SIGINT,
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
58 lambda *args: _shutdown_server_and_raise_sigint())
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
59
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
60 try:
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
61 run_simple(host, port, app,
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
62 threaded=True,
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
63 use_debugger=use_debugger,
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
64 use_reloader=use_reloader)
558
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
65 except SystemExit:
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
66 if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
67 # When using the reloader, if code has changed, the child process
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
68 # will use `sys.exit` to end and let the master process restart
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
69 # it... we need to shutdown the SSE requests otherwise it will
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
70 # not exit.
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
71 _shutdown_server()
9ab005db2592 serve: Improve reloading and shutdown of the preview server.
Ludovic Chabant <ludovic@chabant.com>
parents: 553
diff changeset
72 raise
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
73
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
74
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
75 def run_gunicorn_server(appfactory, gunicorn_options=None):
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
76 from gunicorn.app.base import BaseApplication
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
77
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
78 class PieCrustGunicornApplication(BaseApplication):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
79 def __init__(self, app, options):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
80 self.app = app
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
81 self.options = options
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
82 super(PieCrustGunicornApplication, self).__init__()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
83
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
84 def load_config(self):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
85 for k, v in self.options.items():
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
86 if k in self.cfg.settings and v is not None:
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
87 self.cfg.set(k, v)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
88
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
89 def load(self):
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
90 return self.app
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
91
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
92 app = _get_piecrust_server(appfactory)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
93
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
94 gunicorn_options = gunicorn_options or {}
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
95 app_wrapper = PieCrustGunicornApplication(app, gunicorn_options)
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
96 app_wrapper.run()
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
97
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
98
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
99 def _get_piecrust_server(appfactory, run_sse_check=None):
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
100 from piecrust.serving.middlewares import (
852
4850f8c21b6e core: Start of the big refactor for PieCrust 3.0.
Ludovic Chabant <ludovic@chabant.com>
parents: 738
diff changeset
101 StaticResourcesMiddleware, PieCrustDebugMiddleware)
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
102 from piecrust.serving.server import WsgiServer
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
103 app = WsgiServer(appfactory)
553
cc6f3dbe3048 serve: Extract some of the server's functionality into WSGI middlewares.
Ludovic Chabant <ludovic@chabant.com>
parents: 552
diff changeset
104 app = StaticResourcesMiddleware(app)
666
81d9c3a3a0b5 internal: Get rid of the whole "sub cache" business.
Ludovic Chabant <ludovic@chabant.com>
parents: 663
diff changeset
105 app = PieCrustDebugMiddleware(
852
4850f8c21b6e core: Start of the big refactor for PieCrust 3.0.
Ludovic Chabant <ludovic@chabant.com>
parents: 738
diff changeset
106 app, appfactory, run_sse_check=run_sse_check)
374
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
107 return app
fa3ee8a8ee2d serve: Split the server code in a couple modules inside a `serving` package.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
108