mirror of
https://github.com/sprockets/sprockets.http.git
synced 2024-11-14 19:29:28 +00:00
Add support for `before_run
` callbacks.
This commit is contained in:
parent
d8253fcef2
commit
a1ba8874f6
5 changed files with 60 additions and 13 deletions
19
docs/api.rst
19
docs/api.rst
|
@ -10,9 +10,22 @@ Application Callbacks
|
|||
Starting with version 0.4.0, :func:`sprockets.http.run` augments the
|
||||
:class:`tornado.web.Application` instance with a new attribute named
|
||||
``runner_callbacks`` which is a dictionary of lists of functions to
|
||||
call when specific events occur. The only supported event is
|
||||
**shutdown**. When the application receives a stop signal, it will
|
||||
run each of the callbacks before terminating the application instance.
|
||||
call when specific events occur. The following events are supported:
|
||||
|
||||
:before_run:
|
||||
This set of callbacks is invoked after Tornado forks sub-processes
|
||||
(based on the ``number_of_procs`` setting) and before
|
||||
:meth:`~tornado.ioloop.IOLoop.start` is called. Callbacks can
|
||||
safely access the :class:`~tornado.ioloop.IOLoop` without causing
|
||||
the :meth:`~tornado.ioloop.IOLoop.start` method to explode.
|
||||
|
||||
If any callback raises an exception, then the application is
|
||||
terminated **before** the IOLoop is started.
|
||||
|
||||
:shutdown:
|
||||
When the application receives a stop signal, it will run each of the
|
||||
callbacks before terminating the application instance. Exceptions
|
||||
raised by the callbacks are simply logged.
|
||||
|
||||
See :func:`sprockets.http.run` for a detailed description of how to
|
||||
install the runner callbacks.
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
Release History
|
||||
===============
|
||||
|
||||
`Next Release`_
|
||||
---------------
|
||||
- Add support for the ``before_run`` callback set.
|
||||
|
||||
`1.0.2`_ (10 Dec 2015)
|
||||
----------------------
|
||||
- Add ``log_config`` parameter to ``sprockets.http.run``
|
||||
|
|
|
@ -48,17 +48,20 @@ def run(create_application, settings=None, log_config=None):
|
|||
key, then the application will be configured to run this many processes
|
||||
unless in *debug* mode. This is passed to ``HTTPServer.start``.
|
||||
|
||||
.. rubric:: application.runner_callbacks['shutdown']
|
||||
.. rubric:: application.runner_callbacks
|
||||
|
||||
The ``runner_callbacks`` attribute is a :class:`dict` of lists
|
||||
of functions to call when an event occurs. The *shutdown* key
|
||||
contains functions that are invoked when a stop signal is
|
||||
received *before* the IOLoop is stopped.
|
||||
of functions to call when an event occurs. This attribute will be
|
||||
created **AFTER** `create_application` is called and **BEFORE** this
|
||||
function returns. If the attribute exists on the instance returned
|
||||
from `create_application` , then it will be used as-is.
|
||||
|
||||
This attribute will be created **AFTER** `create_application` is
|
||||
called and **BEFORE** this function returns. If the attribute
|
||||
exists on the instance returned from `create_application` , then
|
||||
it will be used as-is.
|
||||
The *before_run* key contains functions that are invoked after
|
||||
sub-processes are forked (if necessary) and before the IOLoop is
|
||||
started.
|
||||
|
||||
The *shutdown* key contains functions that are invoked when a stop
|
||||
signal is received *before* the IOLoop is stopped.
|
||||
|
||||
"""
|
||||
from . import runner
|
||||
|
|
|
@ -47,8 +47,12 @@ class Runner(object):
|
|||
self.shutdown_limit = 5
|
||||
try:
|
||||
self.application.runner_callbacks.setdefault('shutdown', [])
|
||||
self.application.runner_callbacks.setdefault('before_run', [])
|
||||
except AttributeError:
|
||||
setattr(self.application, 'runner_callbacks', {'shutdown': []})
|
||||
setattr(self.application, 'runner_callbacks', {
|
||||
'shutdown': [],
|
||||
'before_run': [],
|
||||
})
|
||||
|
||||
def start_server(self, port_number, number_of_procs=0):
|
||||
"""
|
||||
|
@ -90,8 +94,18 @@ class Runner(object):
|
|||
tornado decide how many sub-processes to spawn.
|
||||
|
||||
"""
|
||||
iol = ioloop.IOLoop.instance()
|
||||
self.start_server(port_number, number_of_procs)
|
||||
ioloop.IOLoop.instance().start()
|
||||
for callback in self.application.runner_callbacks['before_run']:
|
||||
try:
|
||||
callback(self.application, iol)
|
||||
except Exception:
|
||||
self.logger.error('before_run callback %r cancelled start',
|
||||
callback, exc_info=1)
|
||||
self._shutdown()
|
||||
return
|
||||
|
||||
iol.start()
|
||||
|
||||
def _on_signal(self, signo, frame):
|
||||
self.logger.info('signal %s received, stopping', signo)
|
||||
|
|
13
tests.py
13
tests.py
|
@ -293,10 +293,12 @@ class CallbackTests(unittest.TestCase):
|
|||
super(CallbackTests, self).setUp()
|
||||
self.application = mock.Mock()
|
||||
self.shutdown_callback = mock.Mock()
|
||||
self.before_run_callback = mock.Mock()
|
||||
|
||||
def make_application(self, **settings):
|
||||
self.application.settings = settings.copy()
|
||||
self.application.runner_callbacks = {
|
||||
'before_run': [self.before_run_callback],
|
||||
'shutdown': [self.shutdown_callback],
|
||||
}
|
||||
return self.application
|
||||
|
@ -311,3 +313,14 @@ class CallbackTests(unittest.TestCase):
|
|||
runner.run(8080)
|
||||
runner._shutdown()
|
||||
self.shutdown_callback.assert_called_once_with(self.application)
|
||||
|
||||
def test_that_before_run_callback_invoked(self):
|
||||
iol = mock.Mock(_callbacks=[], _timeouts=[])
|
||||
iol.time.side_effect = time.time
|
||||
with mock.patch('sprockets.http.runner.ioloop') as ioloop:
|
||||
ioloop.IOLoop.instance.return_value = iol
|
||||
with mock.patch('sprockets.http.runner.httpserver'):
|
||||
runner = sprockets.http.runner.Runner(self.make_application())
|
||||
runner.run(8080)
|
||||
self.before_run_callback.assert_called_once_with(
|
||||
self.application, iol)
|
||||
|
|
Loading…
Reference in a new issue