1- """Service methods to queue RO-Crates for validation using the CRS4 validator and Celery ."""
1+ """Service layer for RO-Crate validation requests ."""
22
3- import logging
43import json
4+ import logging
55
6- from flask import jsonify , Response
7-
8- from app .tasks .validation_tasks import (
9- process_validation_task_by_id ,
10- return_ro_crate_validation ,
11- check_ro_crate_exists ,
12- check_validation_exists ,
13- )
6+ from flask import jsonify , Response , current_app
147
8+ from app .crates .ids import validate_crate_id
9+ from app .crates .layout import result_key
10+ from app .crates .resolver import resolve_crate
11+ from app .storage .errors import ObjectNotFound
12+ from app .storage .s3 import S3Backend
13+ from app .tasks .validation_tasks import process_validation_task_by_id
1514from app .utils .config import InvalidAPIUsage
16- from app .utils .minio_utils import get_minio_client
17- from app .validation .runner import validate_metadata
1815from app .validation .results import ValidationStatus
16+ from app .validation .runner import validate_metadata
1917
2018logger = logging .getLogger (__name__ )
2119
2220
21+ def _build_storage () -> S3Backend :
22+ """Build the storage backend from server-side settings."""
23+ settings = current_app .config ["SETTINGS" ]
24+ return S3Backend .from_settings (settings )
25+
26+
2327def queue_ro_crate_validation_task (
24- minio_config ,
25- crate_id ,
26- root_path = None ,
27- profile_name = None ,
28- webhook_url = None ,
29- profiles_path = None ,
28+ crate_id : str , profile_name = None , webhook_url = None
3029) -> tuple [Response , int ]:
3130 """
32- Queues an RO-Crate for validation with Celery.
31+ Resolve a crate by ID and queue it for asynchronous validation.
32+
33+ Credentials and layout are server-side; the request carries only the ID and
34+ optional profile/webhook. Resolution happens before queueing so a bad or
35+ missing crate is reported immediately. ``InvalidCrateId`` / ``CrateNotFound``
36+ / ``AmbiguousCrate`` / ``StorageError`` propagate to the app error handlers.
3337
34- :param minio_config: Access settings for Minio instance containing the RO-Crate.
3538 :param crate_id: The ID of the RO-Crate to validate.
36- :param root_path: The root path containing the RO-Crate.
3739 :param profile_name: The profile to validate against.
38- :param webhook_url: The URL to POST the validation results to.
39- :return: A tuple containing a JSON response and an HTTP status code.
40- :raises: Exception: If an error occurs whilst queueing the task.
40+ :param webhook_url: The URL to POST the validation result to.
41+ :return: A JSON response and HTTP status code.
4142 """
43+ settings = current_app .config ["SETTINGS" ]
44+ storage = _build_storage ()
4245
43- logging .info (f"Processing: { crate_id } , { profile_name } , { webhook_url } " )
44- logging .info (f"Minio Bucket: { minio_config ['bucket' ]} ; Root path: { root_path } " )
45-
46- minio_client = get_minio_client (minio_config )
46+ # Raises if the crate is missing/ambiguous/invalid -> handled as 4xx.
47+ resolve_crate (storage , crate_id , settings .s3_crate_prefix )
4748
48- if check_ro_crate_exists (minio_client , minio_config ["bucket" ], crate_id , root_path ):
49- logging .info ("RO-Crate exists" )
50- else :
51- logging .info ("RO-Crate does not exist" )
52- raise InvalidAPIUsage (f"No RO-Crate with prefix: { crate_id } " , 400 )
53-
54- try :
55- process_validation_task_by_id .delay (
56- minio_config , crate_id , root_path , profile_name , webhook_url , profiles_path
57- )
58- return jsonify ({"message" : "Validation in progress" }), 202
59-
60- except Exception as e :
61- return jsonify ({"error" : str (e )}), 500
49+ process_validation_task_by_id .delay (crate_id , profile_name , webhook_url )
50+ return jsonify ({"message" : "Validation in progress" }), 202
6251
6352
6453def run_metadata_validation (
6554 crate_json : str , profile_name = None , profiles_path = None
6655) -> tuple [Response , int ]:
6756 """
68- Validates RO-Crate metadata synchronously and returns the result inline.
57+ Validate RO-Crate metadata synchronously and return the result inline.
6958
7059 Metadata-only validation is fast and stateless, so it runs in the request
7160 rather than via Celery. Returns 200 for a valid/invalid outcome and 422
@@ -74,9 +63,8 @@ def run_metadata_validation(
7463 :param crate_json: The RO-Crate JSON-LD metadata, as a string.
7564 :param profile_name: The profile to validate against.
7665 :param profiles_path: A path to the profile definition directory.
77- :return: A tuple containing a JSON response and an HTTP status code.
66+ :return: A JSON response and HTTP status code.
7867 """
79-
8068 if not crate_json :
8169 return jsonify ({"error" : "Missing required parameter: crate_json" }), 422
8270
@@ -95,41 +83,25 @@ def run_metadata_validation(
9583 return jsonify (outcome .to_dict ()), status_code
9684
9785
98- def get_ro_crate_validation_task (
99- minio_config : dict ,
100- crate_id : str ,
101- root_path : str ,
102- ) -> tuple [Response , int ]:
86+ def get_ro_crate_validation_task (crate_id : str ) -> tuple [Response , int ]:
10387 """
104- Retrieves an RO-Crate validation result.
88+ Return a crate's stored validation result.
10589
106- :param minio_config: Access settings for Minio instance containing the RO-Crate.
107- :param crate_id: The ID of the RO-Crate to validate.
108- :param root_path: The root path containing the RO-Crate.
109- :return: A tuple containing a JSON response and an HTTP status code.
110- :raises Exception: If an error occurs whilst retreiving validation result
90+ Reads the result object from the results prefix. A missing result yields a
91+ 404; the stored outcome (including a persisted ``error`` outcome) is returned
92+ as-is otherwise.
93+
94+ :param crate_id: The ID of the RO-Crate whose result is requested.
95+ :return: A JSON response and HTTP status code.
11196 """
112- logging .info (f"Retrieving validation for: { crate_id } " )
113-
114- minio_client = get_minio_client (minio_config )
115-
116- if check_ro_crate_exists (minio_client , minio_config ["bucket" ], crate_id , root_path ):
117- logging .info ("RO-Crate exists" )
118- else :
119- logging .info ("RO-Crate does not exist" )
120- raise InvalidAPIUsage (f"No RO-Crate with prefix: { crate_id } " , 400 )
121-
122- if check_validation_exists (
123- minio_client , minio_config ["bucket" ], crate_id , root_path
124- ):
125- logging .info ("Validation result exists" )
126- else :
127- logging .info ("Validation does not exist" )
128- raise InvalidAPIUsage (f"No validation result yet for RO-Crate: { crate_id } " , 400 )
129-
130- return (
131- return_ro_crate_validation (
132- minio_client , minio_config ["bucket" ], crate_id , root_path
133- ),
134- 200 ,
135- )
97+ settings = current_app .config ["SETTINGS" ]
98+ storage = _build_storage ()
99+
100+ validate_crate_id (crate_id ) # raises InvalidCrateId -> 400
101+
102+ try :
103+ data = storage .get_bytes (result_key (settings .s3_results_prefix , crate_id ))
104+ except ObjectNotFound :
105+ raise InvalidAPIUsage (f"No validation result yet for RO-Crate: { crate_id } " , 404 )
106+
107+ return jsonify (json .loads (data )), 200
0 commit comments