diff options
| author | bozo.kopic <bozo@kopic.xyz> | 2022-12-16 21:19:09 +0100 |
|---|---|---|
| committer | bozo.kopic <bozo@kopic.xyz> | 2022-12-16 21:19:09 +0100 |
| commit | e892e413c219dbd8221c5c0f13942fabb51eade9 (patch) | |
| tree | 55b24152eb2e7533017013bf7a1e153c090b26df /src_py | |
| parent | eb32c96d3a6c45018643a7a73e45bf2f01a152ee (diff) | |
server request timeoutv0.4.4
Diffstat (limited to 'src_py')
| -rw-r--r-- | src_py/opcut/main.py | 8 | ||||
| -rw-r--r-- | src_py/opcut/server.py | 43 |
2 files changed, 45 insertions, 6 deletions
diff --git a/src_py/opcut/main.py b/src_py/opcut/main.py index 28bb49e..346afc3 100644 --- a/src_py/opcut/main.py +++ b/src_py/opcut/main.py @@ -70,6 +70,9 @@ def create_argument_parser() -> argparse.ArgumentParser: '--port', metavar='PORT', type=int, default=8080, help="listening TCP port (default 8080)") server.add_argument( + '--timeout', metavar='T', type=float, default=300, + help="single request timeout in seconds (default 300)") + server.add_argument( '--log-level', metavar='LEVEL', default='info', choices=['critical', 'error', 'warning', 'info', 'debug', 'notset'], help="log level (default info)") @@ -98,6 +101,7 @@ def main(): elif args.action == 'server': server(host=args.host, port=args.port, + timeout=args.timeout, log_level=args.log_level) else: @@ -165,6 +169,7 @@ def generate(input_format: typing.Optional[json.Format], def server(host: str, port: int, + timeout: float, log_level: str): logging.config.dictConfig({ 'version': 1, @@ -183,7 +188,8 @@ def server(host: str, async def run(): server = await opcut.server.create(host=host, - port=port) + port=port, + timeout=timeout) try: await server.wait_closing() diff --git a/src_py/opcut/server.py b/src_py/opcut/server.py index 8501aaa..d8665f6 100644 --- a/src_py/opcut/server.py +++ b/src_py/opcut/server.py @@ -12,9 +12,11 @@ from opcut import common async def create(host: str, - port: int + port: int, + timeout: float ) -> 'Server': server = Server() + server._timeout = timeout server._async_group = aio.Group() try: @@ -71,9 +73,14 @@ class Server(aio.Resource): params = common.params_from_json(data) try: - result = await _calculate(method, params) + result = await asyncio.wait_for(_calculate(method, params), + self._timeout) return aiohttp.web.json_response(result) + except asyncio.TimeoutError: + return aiohttp.web.Response(status=400, + text='Request timeout') + except common.UnresolvableError: return aiohttp.web.Response(status=400, text='Result is not solvable') @@ -92,7 +99,13 @@ class Server(aio.Resource): panel = request.query.get('panel') result = common.result_from_json(data) - output = await _generate(output_format, panel, result) + try: + output = await asyncio.wait_for( + _generate(output_format, panel, result), self._timeout) + + except asyncio.TimeoutError: + return aiohttp.web.Response(status=400, + text='Request timeout') if output_format == common.OutputFormat.PDF: content_type = 'application/pdf' @@ -116,7 +129,14 @@ async def _calculate(method, params): stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout_data, stderr_data = await p.communicate(stdint_data) + + stderr_data = None + try: + stdout_data, stderr_data = await p.communicate(stdint_data) + + finally: + if p.returncode is None: + p.terminate() if p.returncode == 0: return json.decode(stdout_data.decode('utf-8')) @@ -124,6 +144,9 @@ async def _calculate(method, params): if p.returncode == 42: raise common.UnresolvableError() + if not stderr_data: + raise Exception() + raise Exception(stderr_data.decode('utf-8')) @@ -137,9 +160,19 @@ async def _generate(output_format, panel, result): stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout_data, stderr_data = await p.communicate(stdint_data) + + stderr_data = None + try: + stdout_data, stderr_data = await p.communicate(stdint_data) + + finally: + if p.returncode is None: + p.terminate() if p.returncode == 0: return stdout_data + if not stderr_data: + raise Exception() + raise Exception(stderr_data.decode('utf-8')) |
