mirror of
https://github.com/sprockets/sprockets-postgres.git
synced 2024-11-14 03:00:19 +00:00
Include a StatusRequestHandler to make things easy
This commit is contained in:
parent
507704a6e7
commit
9a49d769df
3 changed files with 39 additions and 17 deletions
|
@ -9,3 +9,14 @@ functionality for interacting with PostgreSQL.
|
|||
:undoc-members:
|
||||
:private-members:
|
||||
:member-order: bysource
|
||||
|
||||
The :class:`~sprockets_postgres.StatusRequestHandler` is a Tornado
|
||||
:class:`tornado.web.RequestHandler` that can be used for application health
|
||||
monitoring. If the Postgres connection is unavailable, it will report the
|
||||
API as unavailable and return a 503 status code.
|
||||
|
||||
.. autoclass:: sprockets_postgres.StatusRequestHandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:private-members:
|
||||
:member-order: bysource
|
||||
|
|
|
@ -717,3 +717,21 @@ class RequestHandlerMixin:
|
|||
else:
|
||||
LOGGER.debug('Postgres query %s duration: %s',
|
||||
metric_name, duration)
|
||||
|
||||
|
||||
class StatusRequestHandler(web.RequestHandler):
|
||||
"""A RequestHandler that can be used to expose API health or status"""
|
||||
|
||||
async def get(self, *_args, **_kwarg):
|
||||
postgres = await self.application.postgres_status()
|
||||
if not postgres['available']:
|
||||
self.set_status(503)
|
||||
self.write({
|
||||
'application': self.settings.get('service', 'unknown'),
|
||||
'environment': self.settings.get('environment', 'unknown'),
|
||||
'postgres': {
|
||||
'pool_free': postgres['pool_free'],
|
||||
'pool_size': postgres['pool_size']
|
||||
},
|
||||
'status': 'ok' if postgres['available'] else 'unavailable',
|
||||
'version': self.settings.get('version', 'unknown')})
|
||||
|
|
27
tests.py
27
tests.py
|
@ -175,15 +175,6 @@ class NoRowRequestHandler(RequestHandler):
|
|||
'rows': self.cast_data(result.rows)})
|
||||
|
||||
|
||||
class StatusRequestHandler(RequestHandler):
|
||||
|
||||
async def get(self):
|
||||
status = await self.application.postgres_status()
|
||||
if not status['available']:
|
||||
self.set_status(503, 'Database Unavailable')
|
||||
await self.finish(status)
|
||||
|
||||
|
||||
class TransactionRequestHandler(RequestHandler):
|
||||
|
||||
GET_SQL = """\
|
||||
|
@ -315,7 +306,7 @@ class TestCase(testing.SprocketsHttpTestCase):
|
|||
web.url('/no-error', NoErrorRequestHandler),
|
||||
web.url('/no-row', NoRowRequestHandler),
|
||||
web.url('/row-count-no-rows', RowCountNoRowsRequestHandler),
|
||||
web.url('/status', StatusRequestHandler),
|
||||
web.url('/status', sprockets_postgres.StatusRequestHandler),
|
||||
web.url('/timeout-error', TimeoutErrorRequestHandler),
|
||||
web.url('/transaction', TransactionRequestHandler),
|
||||
web.url('/transaction/(?P<test_id>.*)', TransactionRequestHandler),
|
||||
|
@ -329,29 +320,31 @@ class RequestHandlerMixinTestCase(TestCase):
|
|||
def test_postgres_status(self):
|
||||
response = self.fetch('/status')
|
||||
data = json.loads(response.body)
|
||||
self.assertTrue(data['available'])
|
||||
self.assertGreaterEqual(data['pool_size'], 1)
|
||||
self.assertGreaterEqual(data['pool_free'], 1)
|
||||
self.assertEqual(data['status'], 'ok')
|
||||
self.assertGreaterEqual(data['postgres']['pool_size'], 1)
|
||||
self.assertGreaterEqual(data['postgres']['pool_free'], 1)
|
||||
|
||||
@mock.patch('aiopg.pool.Pool.acquire')
|
||||
def test_postgres_status_connect_error(self, acquire):
|
||||
acquire.side_effect = asyncio.TimeoutError()
|
||||
response = self.fetch('/status')
|
||||
self.assertEqual(response.code, 503)
|
||||
self.assertFalse(json.loads(response.body)['available'])
|
||||
data = json.loads(response.body)
|
||||
self.assertEqual(data['status'], 'unavailable')
|
||||
|
||||
def test_postgres_status_not_connected(self):
|
||||
self.app._postgres_connected.clear()
|
||||
response = self.fetch('/status')
|
||||
self.assertEqual(response.code, 503)
|
||||
self.assertFalse(json.loads(response.body)['available'])
|
||||
data = json.loads(response.body)
|
||||
self.assertEqual(data['status'], 'unavailable')
|
||||
|
||||
@mock.patch('aiopg.cursor.Cursor.execute')
|
||||
def test_postgres_status_error(self, execute):
|
||||
execute.side_effect = asyncio.TimeoutError()
|
||||
response = self.fetch('/status')
|
||||
self.assertEqual(response.code, 503)
|
||||
self.assertFalse(json.loads(response.body)['available'])
|
||||
data = json.loads(response.body)
|
||||
self.assertEqual(data['status'], 'unavailable')
|
||||
|
||||
def test_postgres_callproc(self):
|
||||
response = self.fetch('/callproc')
|
||||
|
|
Loading…
Reference in a new issue