Merge branch 'feature/non-blocking-report' into 'master'
Avoid blocking the application when computing the calculator report See merge request cara/cara!214
This commit is contained in:
commit
1044946fa5
2 changed files with 34 additions and 7 deletions
|
|
@ -1,6 +1,8 @@
|
|||
# This module is part of CARA. Please see the repository at
|
||||
# https://gitlab.cern.ch/cara/cara for details of the license and terms of use.
|
||||
|
||||
import asyncio
|
||||
import concurrent.futures
|
||||
import datetime
|
||||
import base64
|
||||
import html
|
||||
|
|
@ -87,7 +89,7 @@ class Missing404Handler(BaseRequestHandler):
|
|||
|
||||
|
||||
class ConcentrationModel(BaseRequestHandler):
|
||||
def post(self):
|
||||
async def post(self):
|
||||
requested_model_config = {
|
||||
name: self.get_argument(name) for name in self.request.arguments
|
||||
}
|
||||
|
|
@ -107,20 +109,27 @@ class ConcentrationModel(BaseRequestHandler):
|
|||
return
|
||||
|
||||
base_url = self.request.protocol + "://" + self.request.host
|
||||
report_generator = self.settings['report_generator']
|
||||
report = report_generator.build_report(base_url, form)
|
||||
report_generator: ReportGenerator = self.settings['report_generator']
|
||||
report_task = self.settings["worker_pool"].submit(
|
||||
report_generator.build_report, base_url, form,
|
||||
)
|
||||
report: str = await asyncio.wrap_future(report_task)
|
||||
self.finish(report)
|
||||
|
||||
|
||||
class StaticModel(BaseRequestHandler):
|
||||
def get(self):
|
||||
async def get(self):
|
||||
form = model_generator.FormData.from_dict(model_generator.baseline_raw_form_data())
|
||||
base_url = self.request.protocol + "://" + self.request.host
|
||||
report_generator = self.settings['report_generator']
|
||||
report = report_generator.build_report(base_url, form)
|
||||
report_generator: ReportGenerator = self.settings['report_generator']
|
||||
report_task = self.settings["worker_pool"].submit(
|
||||
report_generator.build_report, base_url, form,
|
||||
)
|
||||
report: str = await asyncio.wrap_future(report_task)
|
||||
self.finish(report)
|
||||
|
||||
|
||||
|
||||
class LandingPage(BaseRequestHandler):
|
||||
def get(self):
|
||||
template = self.settings["template_environment"].get_template(
|
||||
|
|
@ -226,4 +235,5 @@ def make_app(
|
|||
# COOKIE_SECRET being undefined will result in no login information being
|
||||
# presented to the user.
|
||||
cookie_secret=os.environ.get('COOKIE_SECRET', '<undefined>'),
|
||||
worker_pool=concurrent.futures.ProcessPoolExecutor(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,23 @@ class TestBasicApp(tornado.testing.AsyncHTTPTestCase):
|
|||
|
||||
@tornado.testing.gen_test(timeout=_TIMEOUT)
|
||||
def test_report(self):
|
||||
response = yield self.http_client.fetch(self.get_url('/calculator/baseline-model/result'))
|
||||
requests = [
|
||||
self.http_client.fetch(self.get_url('/calculator/baseline-model/result')),
|
||||
# At the same time, request a non-report page (to check whether the report is blocking).
|
||||
self.http_client.fetch(self.get_url('/calculator/')),
|
||||
]
|
||||
response = yield requests[0]
|
||||
other_response = yield requests[1]
|
||||
|
||||
def end_time(resp):
|
||||
return resp.start_time + resp.request_time
|
||||
|
||||
# The start time is before the other request,
|
||||
# but the end time is after the other request (because it takes longer
|
||||
# to process a report than a simple page).
|
||||
assert response.start_time < other_response.start_time
|
||||
assert end_time(response) > end_time(other_response)
|
||||
|
||||
self.assertEqual(response.code, 200)
|
||||
assert 'CERN HSE' not in response.body.decode()
|
||||
assert 'expected number of new cases is' in response.body.decode()
|
||||
|
|
@ -66,6 +82,7 @@ class TestCernApp(tornado.testing.AsyncHTTPTestCase):
|
|||
assert 'CERN HSE' in response.body.decode()
|
||||
assert 'expected number of new cases is' in response.body.decode()
|
||||
|
||||
|
||||
class TestOpenApp(tornado.testing.AsyncHTTPTestCase):
|
||||
def get_app(self):
|
||||
return cara.apps.calculator.make_app(calculator_prefix="/mycalc")
|
||||
|
|
|
|||
Loading…
Reference in a new issue