diff --git a/v3/crates/engine/src/routes/jsonapi.rs b/v3/crates/engine/src/routes/jsonapi.rs index cebbd034a3e..548ce9a179e 100644 --- a/v3/crates/engine/src/routes/jsonapi.rs +++ b/v3/crates/engine/src/routes/jsonapi.rs @@ -89,8 +89,8 @@ async fn handle_rest_request( let tracer = tracing_util::global_tracer(); let response = tracer .in_span_async( - "handle_request", - "Handle request", + "handle_rest_request", + "Handle rest request", SpanVisibility::User, || { Box::pin(jsonapi::handler_internal( diff --git a/v3/crates/jsonapi/src/handler.rs b/v3/crates/jsonapi/src/handler.rs index 372f9ced021..d7ddb81a844 100644 --- a/v3/crates/jsonapi/src/handler.rs +++ b/v3/crates/jsonapi/src/handler.rs @@ -6,6 +6,7 @@ use super::types::{Catalog, Model, QueryResult, RequestError, State}; use axum::http::{HeaderMap, Method, Uri}; use hasura_authn_core::Session; use metadata_resolve::Metadata; +use tracing_util::SpanVisibility; #[allow(clippy::unused_async)] pub async fn handler_internal<'metadata>( @@ -18,6 +19,8 @@ pub async fn handler_internal<'metadata>( uri: Uri, query_string: jsonapi_library::query::Query, ) -> Result { + let tracer = tracing_util::global_tracer(); + let state = catalog .state_per_role .get(&session.role) @@ -28,19 +31,38 @@ pub async fn handler_internal<'metadata>( None => Err(RequestError::NotFound), Some(model) => { // create the query IR - let query_ir = parse::create_query_ir(model, &http_method, &uri, &query_string)?; + let query_ir = tracer.in_span( + "create_query_ir", + "Create query IR", + SpanVisibility::User, + || parse::create_query_ir(model, &http_method, &uri, &query_string), + )?; + // execute the query with the query-engine - let result = query_engine_execute( - &query_ir, - metadata, - &session, - &http_context, - &request_headers, - ) - .await?; + let result = tracer + .in_span_async( + "query_engine_execute", + "Execute query", + SpanVisibility::User, + || { + Box::pin(query_engine_execute( + &query_ir, + metadata, + &session, + &http_context, + &request_headers, + )) + }, + ) + .await?; // process result to JSON:API compliant response - Ok(process_response::process_result(result)) + tracer.in_span( + "process_response", + "Process response", + SpanVisibility::User, + || Ok(process_response::process_result(result)), + ) } } } diff --git a/v3/crates/jsonapi/src/parse.rs b/v3/crates/jsonapi/src/parse.rs index 796d8545d13..c4d3bfaf605 100644 --- a/v3/crates/jsonapi/src/parse.rs +++ b/v3/crates/jsonapi/src/parse.rs @@ -66,12 +66,14 @@ pub fn create_query_ir( let limit = query_string .page .as_ref() - .map(|page| usize::try_from(page.limit).unwrap()); + .and_then(|page| usize::try_from(page.limit).ok()) + .filter(|page| *page > 0); let offset = query_string .page .as_ref() - .map(|page| usize::try_from(page.offset).unwrap()); + .and_then(|page| usize::try_from(page.offset).ok()) + .filter(|page| *page > 0); // form the model selection let model_selection = open_dds::query::ModelSelection { @@ -86,6 +88,7 @@ pub fn create_query_ir( subgraph, }, }; + let queries = IndexMap::from_iter([( open_dds::query::Alias::new(identifier!("jsonapi_model_query")), open_dds::query::Query::Model(model_selection), diff --git a/v3/crates/jsonapi/tests/passing/no_limits/MediaType.txt b/v3/crates/jsonapi/tests/passing/no_limits/MediaType.txt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/v3/crates/jsonapi/tests/passing/no_limits/MediaType.txt @@ -0,0 +1 @@ + diff --git a/v3/crates/jsonapi/tests/snapshots/jsonapi_golden_tests__result_for_role_admin@no_limits__MediaType.txt.snap b/v3/crates/jsonapi/tests/snapshots/jsonapi_golden_tests__result_for_role_admin@no_limits__MediaType.txt.snap new file mode 100644 index 00000000000..ca3ef7ecd6b --- /dev/null +++ b/v3/crates/jsonapi/tests/snapshots/jsonapi_golden_tests__result_for_role_admin@no_limits__MediaType.txt.snap @@ -0,0 +1,72 @@ +--- +source: crates/jsonapi/tests/jsonapi_golden_tests.rs +expression: result +input_file: crates/jsonapi/tests/passing/no_limits/MediaType.txt +--- +DocumentData { + data: Some( + Multiple( + [ + Resource { + _type: "default_MediaType", + id: "1", + attributes: { + "MediaTypeId": Number(1), + "Name": String("MPEG audio file"), + }, + relationships: None, + links: None, + meta: None, + }, + Resource { + _type: "default_MediaType", + id: "2", + attributes: { + "MediaTypeId": Number(2), + "Name": String("Protected AAC audio file"), + }, + relationships: None, + links: None, + meta: None, + }, + Resource { + _type: "default_MediaType", + id: "3", + attributes: { + "MediaTypeId": Number(3), + "Name": String("Protected MPEG-4 video file"), + }, + relationships: None, + links: None, + meta: None, + }, + Resource { + _type: "default_MediaType", + id: "4", + attributes: { + "MediaTypeId": Number(4), + "Name": String("Purchased AAC audio file"), + }, + relationships: None, + links: None, + meta: None, + }, + Resource { + _type: "default_MediaType", + id: "5", + attributes: { + "MediaTypeId": Number(5), + "Name": String("AAC audio file"), + }, + relationships: None, + links: None, + meta: None, + }, + ], + ), + ), + included: None, + links: None, + meta: None, + jsonapi: None, +} diff --git a/v3/justfile b/v3/justfile index c7cc082eaa0..f4defc1fcf4 100644 --- a/v3/justfile +++ b/v3/justfile @@ -79,7 +79,7 @@ test *ARGS: start-docker-test-deps watch: start-docker-test-deps start-docker-run-deps RUST_LOG=DEBUG \ cargo watch -i "**/*.snap.new" \ - -x test \ + -x 'nextest run' \ -x 'clippy --no-deps' \ -x 'run --bin engine -- \ --otlp-endpoint http://localhost:4317 \