Skip to content

Commit

Permalink
Added /result/info endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita-Smirnov-Exactpro committed Feb 25, 2025
1 parent c6a497b commit b1b7172
Showing 1 changed file with 119 additions and 40 deletions.
159 changes: 119 additions & 40 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ async def req_file_lines(req: Request) -> Response:
path_arg = req.rel_url.query.get('path', '')
start_arg = req.rel_url.query.get('start')
end_arg = req.rel_url.query.get('end')
logger.info('/file?path={path}'.format(path=str(path_arg)))
logger.info(f"/file/lines?path={path_arg}&start={start_arg}&end={end_arg}")
try:
absolute_path = verify_path(path_arg, {results_dir, notebooks_dir})
except Exception as error:
Expand Down Expand Up @@ -658,6 +658,48 @@ def _append_interval(interval: dict[str, int], path_value: str, line_num: int, l
logger.warning(f"The {line_num} line from {path_value} can't be analyzed", error)


def _validate_interval_arg(interval_arg: str) -> int:
try:
interval_size = 0 if interval_arg is None else int(interval_arg)
except ValueError as error:
raise ValueError(f"'{interval_arg}' interval isn't valid int") from error

if interval_size < 0:
raise ValueError(f"'{interval_arg}' interval can't be negative")

return interval_size

def _file_info(path_value: str, interval_value: int) -> dict[str, Any]:
intervals: list[dict[str, int]] = []
line_count = 0
with open(path_value, "r") as f:
interval: dict[str, int] = {}
last_line: str
for line in f:
if interval_value > 0:
last_line = line

if interval_value == 1:
_append_interval(interval, path_value, line_count, line, 'first')
_append_interval(interval, path_value, line_count, line, 'last')
intervals.append(interval)
interval = {}
elif line_count % interval_value == 0:
_append_interval(interval, path_value, line_count, line, 'first')
elif (line_count + 1) % interval_value == 0:
_append_interval(interval, path_value, line_count, line, 'last')
intervals.append(interval)
interval = {}

line_count += 1

if interval:
_append_interval(interval, path_value, line_count - 1, last_line, 'last')
intervals.append(interval)

return {'lines': line_count, 'intervals': intervals}


async def req_file_info(req: Request) -> Response:
"""
---
Expand Down Expand Up @@ -685,7 +727,7 @@ async def req_file_info(req: Request) -> Response:
global logger
path_arg = req.rel_url.query.get('path', '')
interval_arg = req.rel_url.query.get('interval')
logger.info('/file?path={path}'.format(path=str(path_arg)))
logger.info(f"/file/info?path={path_arg}&interval={interval_arg}")
try:
absolute_path = verify_path(path_arg, {results_dir, notebooks_dir})
except Exception as error:
Expand All @@ -695,47 +737,16 @@ async def req_file_info(req: Request) -> Response:
return web.HTTPNotFound()

try:
interval_size = 0 if interval_arg is None else int(interval_arg)
except ValueError as error:
logger.warning(f"'{interval_arg}' interval isn't valid int", error)
return web.HTTPUnprocessableEntity(reason=f"'{interval_arg}' interval isn't valid int")

if interval_size < 0:
logger.warning(f"'{interval_arg}' interval can't be negative")
return web.HTTPUnprocessableEntity(reason=f"'{interval_arg}' interval can't be negative")
interval_value = _validate_interval_arg(interval_arg)
except Exception as error:
logger.warning(f"'{interval_arg}' interval is incorrect", error)
return web.HTTPUnprocessableEntity(reason=f"'{interval_arg}' interval is incorrect: {error}")

try:
intervals: list[dict[str, int]] = []
line_count = 0
with open(absolute_path, "r") as f:
interval: dict[str, int] = {}
last_line: str
for line in f:
if interval_size > 0:
last_line = line

if interval_size == 1:
_append_interval(interval, path_arg, line_count, line, 'first')
_append_interval(interval, path_arg, line_count, line, 'last')
intervals.append(interval)
interval = {}
elif line_count % interval_size == 0:
_append_interval(interval, path_arg, line_count, line, 'first')
elif (line_count + 1) % interval_size == 0:
_append_interval(interval, path_arg, line_count, line, 'last')
intervals.append(interval)
interval = {}

line_count += 1

if interval:
_append_interval(interval, path_arg, line_count - 1, last_line, 'last')
intervals.append(interval)

return web.json_response({'lines': line_count, 'intervals': intervals})
return web.json_response(_file_info(absolute_path, interval_value))
except Exception as error:
logger.warning(f"Lines number calculation for {path_arg} path failure", error)
return web.HTTPInternalServerError(reason=f"Lines number calculation for {path_arg} path failure")
logger.warning(f"Lines number calculation for {absolute_path} path failure", error)
return web.HTTPInternalServerError(reason=f"Lines number calculation for {absolute_path} path failure: {error}")


async def req_result(req: Request) -> Response:
Expand Down Expand Up @@ -791,6 +802,73 @@ async def req_result(req: Request) -> Response:
return web.HTTPNotFound()


async def req_result_info(req: Request) -> Response:
"""
---
description: This end-point allows to get result info.
args:
- id (required) - id of run task
- interval (optional) - interval size for splitting file to blocks and extract firs / last display-timestamp for them
tags:
- Execution operation
produces:
- application/json
responses:
"200":
description: successful operation. Return different data depending on status:
'in progress': return json with task's status
'success': return result file's info json.
'error': return json with reason of failed run
"400":
description: failed operation. body with parameters not present.
"404":
description: failed operation. requested task doesn't exist
or resulting file doesn't exist or status is unknown.
"422"
interval isn't positive int
"500":
file can't be read
"""
global tasks
global logger
task_id = req.rel_url.query.get('id')
interval_arg = req.rel_url.query.get('interval')
logger.debug(f"/result/info?id={task_id}&interval={interval_arg}")
task: TaskMetadata = tasks.get(task_id)
if task is None:
return web.HTTPNotFound(reason="Requested task doesn't exist")

try:
interval_value = _validate_interval_arg(interval_arg)
except Exception as error:
logger.warning(f"'{interval_arg}' interval is incorrect", error)
return web.HTTPUnprocessableEntity(reason=f"'{interval_arg}' interval is incorrect: {error}")

status = task.status
if status == TaskStatus.IN_PROGRESS:
return web.json_response({'status': status.value})
elif status == TaskStatus.SUCCESS:
path_value = task.result
if not path_value or not os.path.isfile(path_value):
return web.HTTPNotFound(reason="Resulting file doesn't exist")

try:
info: dict[str, Any] = _file_info(path_value, interval_value)
info['status'] = status.value
info['path'] = path_value
return web.json_response(info)
except Exception as error:
logger.warning(f"Lines number calculation for {path_value} path failure", error)
return web.HTTPInternalServerError(
reason=f"Lines number calculation for {path_value} path failure: {error}")

elif status == TaskStatus.FAILED:
error: Exception = task.result
return web.json_response({'status': status.value, 'result': str(error)})
else:
return web.HTTPNotFound()


async def req_stop(req: Request) -> Response:
"""
---
Expand Down Expand Up @@ -839,6 +917,7 @@ async def req_stop(req: Request) -> Response:
app.router.add_route('GET', "/file/info", req_file_info)
app.router.add_route('POST', "/execute", req_launch)
app.router.add_route('GET', "/result", req_result)
app.router.add_route('GET', "/result/info", req_result_info)
app.router.add_route('POST', "/stop", req_stop)
setup_swagger(app)
logger.info('starting server')
Expand Down

0 comments on commit b1b7172

Please sign in to comment.