aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--src_py/opcut/main.py8
-rw-r--r--src_py/opcut/server.py43
3 files changed, 46 insertions, 7 deletions
diff --git a/VERSION b/VERSION
index 17b2ccd..6f2743d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.3
+0.4.4
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'))