From 617bfc10c32f4dfa3d601a1eb5368a29b441c3a1 Mon Sep 17 00:00:00 2001 From: Marco Cucchi Date: Mon, 2 Dec 2024 18:27:57 +0100 Subject: [PATCH 1/3] check request validity --- cads_processing_api_service/clients.py | 1 + cads_processing_api_service/costing.py | 14 ++++++++++++++ cads_processing_api_service/models.py | 1 + 3 files changed, 16 insertions(+) diff --git a/cads_processing_api_service/clients.py b/cads_processing_api_service/clients.py index 2ba0e3e..071b317 100644 --- a/cads_processing_api_service/clients.py +++ b/cads_processing_api_service/clients.py @@ -240,6 +240,7 @@ def post_process_execution( adaptor = adaptors.instantiate_adaptor(adaptor_properties=adaptor_properties) try: request_inputs = adaptor.normalise_request(request_body.get("inputs", {})) + request_inputs = adaptor.check_validity(request_inputs) except cads_adaptors.exceptions.InvalidRequest as exc: raise exceptions.InvalidRequest(detail=str(exc)) from exc if dataset.api_enforce_constraints: diff --git a/cads_processing_api_service/costing.py b/cads_processing_api_service/costing.py index a73fee5..f4b5df8 100644 --- a/cads_processing_api_service/costing.py +++ b/cads_processing_api_service/costing.py @@ -18,6 +18,7 @@ from typing import Any import cads_adaptors +import cads_adaptors.exceptions import cads_catalogue import fastapi @@ -34,6 +35,7 @@ class RequestOrigin(str, enum.Enum): def estimate_cost( process_id: str = fastapi.Path(...), request_origin: RequestOrigin = fastapi.Query("api"), + mandatory_inputs: bool = fastapi.Query(False), execution_content: models.Execute = fastapi.Body(...), ) -> models.RequestCost: """ @@ -61,12 +63,24 @@ def estimate_cost( resource_id=process_id, table=table, session=catalogue_session ) adaptor_properties = adaptors.get_adaptor_properties(dataset) + if not mandatory_inputs: + request_is_valid = False + else: + try: + adaptor = adaptors.instantiate_adaptor( + adaptor_properties=adaptor_properties + ) + request = adaptor.check_validity(request.get("inputs", {})) + request_is_valid = True + except cads_adaptors.exceptions.InvalidRequest: + request_is_valid = False costing_info = costing.compute_costing( request.get("inputs", {}), adaptor_properties, request_origin ) cost = costing.compute_highest_cost_limit_ratio(costing_info) if costing_info.cost_bar_steps: cost.cost_bar_steps = costing_info.cost_bar_steps + costing_info.request_is_valid = request_is_valid return cost diff --git a/cads_processing_api_service/models.py b/cads_processing_api_service/models.py index e3476bc..6ab223c 100644 --- a/cads_processing_api_service/models.py +++ b/cads_processing_api_service/models.py @@ -80,6 +80,7 @@ class CostingInfo(pydantic.BaseModel): costs: dict[str, float] = {} limits: dict[str, float] = {} cost_bar_steps: list[int] | None = None + request_is_valid: bool = True class RequestCost(pydantic.BaseModel): From 120e1991eab8c63b17fcdfee47c0f79a8f3ed2de Mon Sep 17 00:00:00 2001 From: Marco Cucchi Date: Tue, 3 Dec 2024 18:23:02 +0100 Subject: [PATCH 2/3] check_validity returns None if request is valid --- cads_processing_api_service/clients.py | 2 +- cads_processing_api_service/costing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cads_processing_api_service/clients.py b/cads_processing_api_service/clients.py index 071b317..9e0750b 100644 --- a/cads_processing_api_service/clients.py +++ b/cads_processing_api_service/clients.py @@ -240,7 +240,7 @@ def post_process_execution( adaptor = adaptors.instantiate_adaptor(adaptor_properties=adaptor_properties) try: request_inputs = adaptor.normalise_request(request_body.get("inputs", {})) - request_inputs = adaptor.check_validity(request_inputs) + _ = adaptor.check_validity(request_inputs) except cads_adaptors.exceptions.InvalidRequest as exc: raise exceptions.InvalidRequest(detail=str(exc)) from exc if dataset.api_enforce_constraints: diff --git a/cads_processing_api_service/costing.py b/cads_processing_api_service/costing.py index f4b5df8..8b4e5be 100644 --- a/cads_processing_api_service/costing.py +++ b/cads_processing_api_service/costing.py @@ -70,7 +70,7 @@ def estimate_cost( adaptor = adaptors.instantiate_adaptor( adaptor_properties=adaptor_properties ) - request = adaptor.check_validity(request.get("inputs", {})) + _ = adaptor.check_validity(request.get("inputs", {})) request_is_valid = True except cads_adaptors.exceptions.InvalidRequest: request_is_valid = False From 9b5ad0d35ae7b7d5f44e8747103d93aed817746c Mon Sep 17 00:00:00 2001 From: Marco Cucchi Date: Tue, 3 Dec 2024 18:28:21 +0100 Subject: [PATCH 3/3] wrap request validity check in function --- cads_processing_api_service/costing.py | 46 ++++++++++++++++++++------ 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/cads_processing_api_service/costing.py b/cads_processing_api_service/costing.py index 8b4e5be..b2f28fe 100644 --- a/cads_processing_api_service/costing.py +++ b/cads_processing_api_service/costing.py @@ -63,17 +63,11 @@ def estimate_cost( resource_id=process_id, table=table, session=catalogue_session ) adaptor_properties = adaptors.get_adaptor_properties(dataset) - if not mandatory_inputs: - request_is_valid = False - else: - try: - adaptor = adaptors.instantiate_adaptor( - adaptor_properties=adaptor_properties - ) - _ = adaptor.check_validity(request.get("inputs", {})) - request_is_valid = True - except cads_adaptors.exceptions.InvalidRequest: - request_is_valid = False + request_is_valid = check_request_validity( + request=request, + mandatory_inputs=mandatory_inputs, + adaptor_properties=adaptor_properties, + ) costing_info = costing.compute_costing( request.get("inputs", {}), adaptor_properties, request_origin ) @@ -84,6 +78,36 @@ def estimate_cost( return cost +def check_request_validity( + request: dict[str, Any], mandatory_inputs: bool, adaptor_properties: dict[str, Any] +) -> bool: + """ + Check if the request is valid. + + Parameters + ---------- + request : dict[str, Any] + Request to be processed. + mandatory_inputs : bool + Whether mandatory inputs have been provided. + adaptor_properties : dict[str, Any] + Adaptor properties. + + Returns + ------- + bool + Whether the request is valid. + """ + if not mandatory_inputs: + return False + try: + adaptor = adaptors.instantiate_adaptor(adaptor_properties=adaptor_properties) + _ = adaptor.check_validity(request.get("inputs", {})) + return True + except cads_adaptors.exceptions.InvalidRequest: + return False + + def compute_highest_cost_limit_ratio( costing_info: models.CostingInfo, ) -> models.RequestCost: