This is an automated email from the ASF dual-hosted git repository. skperez pushed a commit to branch SDAP-500 in repository https://gitbox.apache.org/repos/asf/incubator-sdap-nexus.git
commit 4ab2f9b4a4f72a34b922cb496cedb87e684335b7 Author: skorper <[email protected]> AuthorDate: Thu Nov 16 13:22:09 2023 -0800 pagination improvements --- .../webservice/algorithms/doms/ExecutionStatus.py | 5 ++- .../webservice/algorithms/doms/ResultsRetrieval.py | 2 ++ analysis/webservice/algorithms_spark/Matchup.py | 10 +++--- analysis/webservice/apidocs/openapi.yml | 14 ++++++++ .../webservice/webmodel/NexusExecutionResults.py | 40 ++++++++++++++-------- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/analysis/webservice/algorithms/doms/ExecutionStatus.py b/analysis/webservice/algorithms/doms/ExecutionStatus.py index 17c6ca9..63cf423 100644 --- a/analysis/webservice/algorithms/doms/ExecutionStatus.py +++ b/analysis/webservice/algorithms/doms/ExecutionStatus.py @@ -42,6 +42,8 @@ class ExecutionStatusHandler(BaseDomsHandler.BaseDomsQueryCalcHandler): except ValueError: raise NexusProcessingException(reason='"id" argument must be a valid uuid', code=400) + filename = request.get_argument('filename', None) + # Check if the job is done with ResultsRetrieval(self.config) as retrieval: try: @@ -74,5 +76,6 @@ class ExecutionStatusHandler(BaseDomsHandler.BaseDomsQueryCalcHandler): host=host, num_primary_matched=execution_stats.get('numPrimaryMatched'), num_secondary_matched=execution_stats.get('numSecondaryMatched'), - num_unique_secondaries=execution_stats.get('numUniqueSecondaries') + num_unique_secondaries=execution_stats.get('numUniqueSecondaries'), + filename=filename ) diff --git a/analysis/webservice/algorithms/doms/ResultsRetrieval.py b/analysis/webservice/algorithms/doms/ResultsRetrieval.py index f03c1ca..cdec929 100644 --- a/analysis/webservice/algorithms/doms/ResultsRetrieval.py +++ b/analysis/webservice/algorithms/doms/ResultsRetrieval.py @@ -45,6 +45,8 @@ class DomsResultsRetrievalHandler(BaseDomsHandler.BaseDomsQueryCalcHandler): simple_results = computeOptions.get_boolean_arg("simpleResults", default=False) + filename = computeOptions.get_argument("filename", default=None) + with ResultsStorage.ResultsRetrieval(self.config) as storage: params, stats, data = storage.retrieveResults(execution_id, trim_data=simple_results, page_num=page_num, page_size=page_size) diff --git a/analysis/webservice/algorithms_spark/Matchup.py b/analysis/webservice/algorithms_spark/Matchup.py index 8955d95..7c7f551 100644 --- a/analysis/webservice/algorithms_spark/Matchup.py +++ b/analysis/webservice/algorithms_spark/Matchup.py @@ -219,12 +219,13 @@ class Matchup(NexusCalcSparkTornadoHandler): end_seconds_from_epoch = int((end_time - EPOCH).total_seconds()) prioritize_distance = request.get_boolean_arg("prioritizeDistance", default=True) + filename = request.get_argument('filename', default=None) return bounding_polygon, primary_ds_name, secondary_ds_names, parameter_s, \ start_time, start_seconds_from_epoch, end_time, end_seconds_from_epoch, \ depth_min, depth_max, time_tolerance, radius_tolerance, \ - platforms, match_once, prioritize_distance + platforms, match_once, prioritize_distance, filename def get_job_pool(self, tile_ids): if len(tile_ids) > LARGE_JOB_THRESHOLD: @@ -302,7 +303,7 @@ class Matchup(NexusCalcSparkTornadoHandler): bounding_polygon, primary_ds_name, secondary_ds_names, parameter_s, \ start_time, start_seconds_from_epoch, end_time, end_seconds_from_epoch, \ depth_min, depth_max, time_tolerance, radius_tolerance, \ - platforms, match_once, prioritize_distance = self.parse_arguments(request) + platforms, match_once, prioritize_distance, filename = self.parse_arguments(request) args = { "primary": primary_ds_name, @@ -375,9 +376,8 @@ class Matchup(NexusCalcSparkTornadoHandler): start=start, prioritize_distance=prioritize_distance )) - - request.requestHandler.redirect(f'/job?id={execution_id}') - + filename_param = f'&filename={filename}' if filename else '' + request.requestHandler.redirect(f'/job?id={execution_id}{filename_param}') @classmethod def convert_to_matches(cls, spark_result): diff --git a/analysis/webservice/apidocs/openapi.yml b/analysis/webservice/apidocs/openapi.yml index b719ad8..8c6efdc 100644 --- a/analysis/webservice/apidocs/openapi.yml +++ b/analysis/webservice/apidocs/openapi.yml @@ -166,6 +166,13 @@ paths: type: boolean default: true example: true + - in: query + name: filename + description: | + Optional filename. Will be passed into /job and results links + required: false + schema: + type: string responses: '200': description: Successful operation @@ -689,6 +696,13 @@ paths: type: string format: uuid example: c864a51b-3d87-4872-9070-632820b1cae2 + - in: query + name: filename + description: | + Optional filename. Will be passed into /job results links + required: false + schema: + type: string /job/cancel: get: summary: | diff --git a/analysis/webservice/webmodel/NexusExecutionResults.py b/analysis/webservice/webmodel/NexusExecutionResults.py index 7dd7af9..47a891a 100644 --- a/analysis/webservice/webmodel/NexusExecutionResults.py +++ b/analysis/webservice/webmodel/NexusExecutionResults.py @@ -27,15 +27,17 @@ class ExecutionStatus(Enum): CANCELLED = 'cancelled' -def construct_job_status(job_state, created, updated, execution_id, params, host, message=''): +def construct_job_status(job_state, created, updated, execution_id, params, host, message='', + filename=None): + filename_param = f'&filename={filename}' if filename else '' return { 'status': job_state.value, 'message': message, 'createdAt': created, 'updatedAt': updated, 'links': [{ - 'href': f'{host}/job?id={execution_id}', - 'title': 'The current page', + 'href': f'{host}/job?id={execution_id}{filename_param}', + 'title': 'Get job status - the current page', 'type': 'application/json', 'rel': 'self' }], @@ -45,14 +47,15 @@ def construct_job_status(job_state, created, updated, execution_id, params, host def construct_done(status, created, completed, execution_id, params, host, - num_primary_matched, num_secondary_matched, num_unique_secondaries): + num_primary_matched, num_secondary_matched, num_unique_secondaries, filename): job_body = construct_job_status( status, created, completed, execution_id, params, - host + host, + filename=filename ) # Add stats to body job_body['totalPrimaryMatched'] = num_primary_matched @@ -61,6 +64,8 @@ def construct_done(status, created, completed, execution_id, params, host, if num_primary_matched > 0 else 0 job_body['totalUniqueSecondaryMatched'] = num_unique_secondaries + filename_param = f'&filename={filename}' if filename else '' + # Construct urls formats = [ ('CSV', 'text/csv'), @@ -68,8 +73,8 @@ def construct_done(status, created, completed, execution_id, params, host, ('NETCDF', 'binary/octet-stream') ] data_links = [{ - 'href': f'{host}/cdmsresults?id={execution_id}&output={output_format}', - 'title': 'Download results', + 'href': f'{host}/cdmsresults?id={execution_id}&output={output_format}{filename_param}', + 'title': f'Download {output_format} results', 'type': mime, 'rel': 'data' } for output_format, mime in formats] @@ -77,14 +82,15 @@ def construct_done(status, created, completed, execution_id, params, host, return job_body -def construct_running(status, created, execution_id, params, host): +def construct_running(status, created, execution_id, params, host, filename): job_body = construct_job_status( status, created, None, execution_id, params, - host + host, + filename=filename ) job_body['links'].append({ 'href': f'{host}/job/cancel?id={execution_id}', @@ -94,7 +100,7 @@ def construct_running(status, created, execution_id, params, host): return job_body -def construct_error(status, created, completed, execution_id, message, params, host): +def construct_error(status, created, completed, execution_id, message, params, host, filename): return construct_job_status( status, created, @@ -102,25 +108,27 @@ def construct_error(status, created, completed, execution_id, message, params, h execution_id, params, host, - message + message, + filename=filename ) -def construct_cancelled(status, created, completed, execution_id, params, host): +def construct_cancelled(status, created, completed, execution_id, params, host, filename): return construct_job_status( status, created, completed, execution_id, params, - host + host, + filename=filename ) class NexusExecutionResults: def __init__(self, status=None, created=None, completed=None, execution_id=None, message='', params=None, host=None, status_code=200, num_primary_matched=None, - num_secondary_matched=None, num_unique_secondaries=None): + num_secondary_matched=None, num_unique_secondaries=None, filename=None): self.status_code = status_code self.status = status self.created = created @@ -132,6 +140,7 @@ class NexusExecutionResults: self.num_primary_matched = num_primary_matched self.num_secondary_matched = num_secondary_matched self.num_unique_secondaries = num_unique_secondaries + self.filename = filename def toJson(self): params = { @@ -139,7 +148,8 @@ class NexusExecutionResults: 'created': self.created, 'execution_id': self.execution_id, 'params': self.execution_params, - 'host': self.host + 'host': self.host, + 'filename': self.filename } if self.status == ExecutionStatus.SUCCESS: params['completed'] = self.completed
