Merge pull request #24 from dave-shawley/reuse-that-address

Reuse the listening socket address
This commit is contained in:
Gavin M. Roy 2018-01-29 11:26:21 -05:00 committed by GitHub
commit 615577e092
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 79 additions and 14 deletions

8
.readthedocs.yml Normal file
View file

@ -0,0 +1,8 @@
---
formats: # only HTML & json
- none
requirements_file: requires/development.txt
build:
image: latest
python:
version: 3

View file

@ -10,7 +10,6 @@ install:
- pip install -e .
script:
- nosetests --with-coverage
- ./setup.py build_sphinx
after_success:
- codecov
sudo: false

View file

@ -1,4 +1,4 @@
Copyright (c) 2015-2016 AWeber Communications
Copyright (c) 2015-2017 AWeber Communications
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View file

@ -1,5 +1,8 @@
sprockets.http
==============
|Version| |ReadTheDocs| |Travis| |Coverage|
The goal of this library is to make it a little easier to develop great
HTTP API services using the Tornado web framework. It concentrates on
running applications in a reliable & resilient manner and handling errors
@ -235,3 +238,12 @@ the standard ``serve_traceback`` Tornado option is enabled.
If the ``sprockets.mixins.mediatype.ContentMixin`` is also extended by your
base class, ``write-error`` will use the ``ContentMixin.send_response`` method
for choosing the appropriate response format and sending the error response.
.. |Coverage| image:: https://codecov.io/github/sprockets/sprockets.http/coverage.svg?branch=master
:target: https://codecov.io/github/sprockets/sprockets.http
.. |ReadTheDocs| image:: http://readthedocs.org/projects/sprocketshttp/badge/?version=master
:target: https://sprocketshttp.readthedocs.io/
.. |Travis| image:: https://travis-ci.org/sprockets/sprockets.http.svg
:target: https://travis-ci.org/sprockets/sprockets.http
.. |Version| image:: https://badge.fury.io/py/sprockets.http.svg
:target: https://pypi.python.org/pypi/sprockets.http/

View file

@ -32,8 +32,6 @@ html_theme_options = {
'github_repo': 'sprockets.http',
'description': 'Tornado application runner',
'github_banner': True,
'travis_button': True,
'codecov_button': True,
}
html_static_path = ['_static']

View file

@ -3,8 +3,12 @@
Release History
===============
`Next Release`_
---------------
- Enable port reuse for Tornado versions newer than 4.3.
`1.4.2`_ (25 Jan 2018)
---------------------
----------------------
- Allow max_body_size and max_buffer_size to be specified on the http server.
`1.4.1`_ (3 Jan 2018)

View file

@ -1,6 +1,7 @@
-rinstallation.txt
-rtesting.txt
coverage==4.4.2
flake8==3.5.0
sphinx==1.5.6
sphinxcontrib-httpdomain==1.5.0
tox==1.9.2

View file

@ -12,6 +12,7 @@ import signal
import sys
from tornado import httpserver, ioloop
import tornado
import sprockets.http.app
@ -90,7 +91,12 @@ class Runner(object):
self.server.listen(port_number)
else:
self.logger.info('starting processes on port %d', port_number)
self.server.bind(port_number)
if tornado.version_info >= (4, 4):
self.server.bind(port_number, reuse_port=True)
else:
self.logger.warning('port reuse disabled, please upgrade to'
'at least Tornado 4.4')
self.server.bind(port_number)
self.server.start(number_of_procs)
def stop_server(self):
@ -125,7 +131,7 @@ class Runner(object):
try:
self.application.start(iol)
except:
except Exception:
self.logger.exception('application terminated during start, '
'exiting')
sys.exit(70)

View file

@ -14,7 +14,8 @@ except ImportError:
import mock
open_name = '__builtin__.open'
from tornado import concurrent, httputil, ioloop, testing, web
from tornado import concurrent, httpserver, httputil, ioloop, testing, web
import tornado
import sprockets.http.mixins
import sprockets.http.runner
@ -383,7 +384,7 @@ class RunnerTests(MockHelper, unittest.TestCase):
ioloop_module = self.start_mock('sprockets.http.runner.ioloop')
ioloop_module.IOLoop.instance.return_value = self.io_loop
self.http_server = mock.Mock()
self.http_server = mock.Mock(spec=httpserver.HTTPServer)
self.httpserver_module = \
self.start_mock('sprockets.http.runner.httpserver')
self.httpserver_module.HTTPServer.return_value = self.http_server
@ -402,9 +403,24 @@ class RunnerTests(MockHelper, unittest.TestCase):
def test_that_production_run_starts_in_multiprocess_mode(self):
runner = sprockets.http.runner.Runner(self.application)
runner.run(8000)
self.http_server.bind.assert_called_once_with(8000)
self.assertTrue(self.http_server.bind.called)
args, kwargs = self.http_server.bind.call_args_list[0]
self.assertEqual(args, (8000, ))
self.http_server.start.assert_called_once_with(0)
@unittest.skipUnless(tornado.version_info >= (4, 4),
'port reuse requries newer tornado')
def test_that_production_enables_reuse_port(self):
runner = sprockets.http.runner.Runner(self.application)
runner.run(8000)
self.assertTrue(self.http_server.bind.called)
args, kwargs = self.http_server.bind.call_args_list[0]
self.assertEqual(args, (8000, ))
self.assertEqual(kwargs['reuse_port'], True)
def test_that_debug_run_starts_in_singleprocess_mode(self):
self.application.settings['debug'] = True
runner = sprockets.http.runner.Runner(self.application)

29
tox.ini
View file

@ -1,13 +1,34 @@
[tox]
envlist = py27,py34,py35,pypy,pypy3
envlist = py27,py34,py35,pypy,pypy3,tornado42,tornado44,tornado45
indexserver =
default = https://pypi.python.org/simple
toxworkdir = build/tox
skip_missing_interpreters = True
use_develop = True
[testenv]
commands =
./setup.py develop
nosetests []
nosetests -v
deps =
-rrequires/testing.txt
-rrequires/testing.txt
[testenv:tornado42]
commands =
{envbindir}/pip install tornado>=4.2,<4.3
{[testenv]commands}
[testenv:tornado43]
commands =
{envbindir}/pip install tornado>=4.3,<4.4
{[testenv]commands}
[testenv:tornado44]
commands =
{envbindir}/pip install tornado>=4.4,<4.5
{[testenv]commands}
[testenv:tornado45]
commands =
{envbindir}/pip install tornado>=4.5,<4.6
{[testenv]commands}