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
|
Starting with version 0.4.0, :func:`sprockets.http.run` augments the
|
||||||
:class:`tornado.web.Application` instance with a new attribute named
|
:class:`tornado.web.Application` instance with a new attribute named
|
||||||
``runner_callbacks`` which is a dictionary of lists of functions to
|
``runner_callbacks`` which is a dictionary of lists of functions to
|
||||||
call when specific events occur. The only supported event is
|
call when specific events occur. The following events are supported:
|
||||||
**shutdown**. When the application receives a stop signal, it will
|
|
||||||
run each of the callbacks before terminating the application instance.
|
: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
|
See :func:`sprockets.http.run` for a detailed description of how to
|
||||||
install the runner callbacks.
|
install the runner callbacks.
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
Release History
|
Release History
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
`Next Release`_
|
||||||
|
---------------
|
||||||
|
- Add support for the ``before_run`` callback set.
|
||||||
|
|
||||||
`1.0.2`_ (10 Dec 2015)
|
`1.0.2`_ (10 Dec 2015)
|
||||||
----------------------
|
----------------------
|
||||||
- Add ``log_config`` parameter to ``sprockets.http.run``
|
- 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
|
key, then the application will be configured to run this many processes
|
||||||
unless in *debug* mode. This is passed to ``HTTPServer.start``.
|
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
|
The ``runner_callbacks`` attribute is a :class:`dict` of lists
|
||||||
of functions to call when an event occurs. The *shutdown* key
|
of functions to call when an event occurs. This attribute will be
|
||||||
contains functions that are invoked when a stop signal is
|
created **AFTER** `create_application` is called and **BEFORE** this
|
||||||
received *before* the IOLoop is stopped.
|
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
|
The *before_run* key contains functions that are invoked after
|
||||||
called and **BEFORE** this function returns. If the attribute
|
sub-processes are forked (if necessary) and before the IOLoop is
|
||||||
exists on the instance returned from `create_application` , then
|
started.
|
||||||
it will be used as-is.
|
|
||||||
|
The *shutdown* key contains functions that are invoked when a stop
|
||||||
|
signal is received *before* the IOLoop is stopped.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from . import runner
|
from . import runner
|
||||||
|
|
|
@ -47,8 +47,12 @@ class Runner(object):
|
||||||
self.shutdown_limit = 5
|
self.shutdown_limit = 5
|
||||||
try:
|
try:
|
||||||
self.application.runner_callbacks.setdefault('shutdown', [])
|
self.application.runner_callbacks.setdefault('shutdown', [])
|
||||||
|
self.application.runner_callbacks.setdefault('before_run', [])
|
||||||
except AttributeError:
|
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):
|
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.
|
tornado decide how many sub-processes to spawn.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
iol = ioloop.IOLoop.instance()
|
||||||
self.start_server(port_number, number_of_procs)
|
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):
|
def _on_signal(self, signo, frame):
|
||||||
self.logger.info('signal %s received, stopping', signo)
|
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()
|
super(CallbackTests, self).setUp()
|
||||||
self.application = mock.Mock()
|
self.application = mock.Mock()
|
||||||
self.shutdown_callback = mock.Mock()
|
self.shutdown_callback = mock.Mock()
|
||||||
|
self.before_run_callback = mock.Mock()
|
||||||
|
|
||||||
def make_application(self, **settings):
|
def make_application(self, **settings):
|
||||||
self.application.settings = settings.copy()
|
self.application.settings = settings.copy()
|
||||||
self.application.runner_callbacks = {
|
self.application.runner_callbacks = {
|
||||||
|
'before_run': [self.before_run_callback],
|
||||||
'shutdown': [self.shutdown_callback],
|
'shutdown': [self.shutdown_callback],
|
||||||
}
|
}
|
||||||
return self.application
|
return self.application
|
||||||
|
@ -311,3 +313,14 @@ class CallbackTests(unittest.TestCase):
|
||||||
runner.run(8080)
|
runner.run(8080)
|
||||||
runner._shutdown()
|
runner._shutdown()
|
||||||
self.shutdown_callback.assert_called_once_with(self.application)
|
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