diff --git a/README.md b/README.md index d19a148..ff28e29 100644 --- a/README.md +++ b/README.md @@ -109,13 +109,13 @@ Get the visit directory for a beamline and visit } ``` -#### configuration -Get the current configuration values for the given beamline +#### configurations +Get the current configuration values, optionally filtering for a specific beamline ##### Query ```graphql { - configuration(beamline: "i22") { + configurations(beamlineFilter: "i22") { visitTemplate scanTemplate detectorTemplate @@ -127,12 +127,14 @@ Get the current configuration values for the given beamline ##### Response ```json { - "configuration": { - "visitTemplate": "/data/{instrument}/data/{year}/{visit}", - "scanTemplate": "{subdirectory}/{instrument}-{scan_number}", - "detectorTemplate": "{subdirectory}/{instrument}-{scan_number}-{detector}", - "latestScanNumber": 20839 - } + "configurations": [ + { + "visitTemplate": "/tmp/{instrument}/data/{year}/{visit}", + "scanTemplate": "{subdirectory}/{instrument}-{scan_number}", + "detectorTemplate": "{subdirectory}/{instrument}-{scan_number}-{detector}", + "latestScanNumber": 12345 + } + ] } ``` diff --git a/src/db_service.rs b/src/db_service.rs index 6e77590..8c7c410 100644 --- a/src/db_service.rs +++ b/src/db_service.rs @@ -303,6 +303,15 @@ impl SqliteScanPathService { .ok_or(ConfigurationError::MissingBeamline(beamline.into())) } + pub async fn configurations(&self) -> Result, ConfigurationError> { + Ok(query_as!(DbBeamlineConfig, "SELECT * FROM beamline") + .fetch_all(&self.pool) + .await? + .into_iter() + .map(BeamlineConfiguration::from) + .collect()) + } + pub async fn next_scan_configuration( &self, beamline: &str, @@ -347,7 +356,7 @@ impl fmt::Debug for SqliteScanPathService { } } -mod error { +pub(crate) mod error { use std::error::Error; use std::fmt::{self, Display}; @@ -604,6 +613,33 @@ mod db_tests { assert_eq!(fb.extension, "ext"); } + #[rstest] + #[test] + async fn configurations(#[future(awt)] db: SqliteScanPathService) { + let confs = ok!(db.configurations()); + assert_eq!(confs.len(), 1); + let conf = confs.first().unwrap(); + assert_eq!(conf.name(), "i22"); + assert_eq!(conf.scan_number(), 122); + assert_eq!( + conf.visit().unwrap().to_string(), + "/tmp/{instrument}/data/{year}/{visit}" + ); + assert_eq!( + conf.scan().unwrap().to_string(), + "{subdirectory}/{instrument}-{scan_number}" + ); + assert_eq!( + conf.detector().unwrap().to_string(), + "{subdirectory}/{instrument}-{scan_number}-{detector}" + ); + let Some(fb) = conf.fallback() else { + panic!("Missing fallback configuration"); + }; + assert_eq!(fb.directory, "/tmp/trackers"); + assert_eq!(fb.extension, "ext"); + } + type Update = BeamlineConfigurationUpdate; #[rstest] diff --git a/src/graphql.rs b/src/graphql.rs index 0f858bc..26a9c5c 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -38,6 +38,7 @@ use crate::cli::ServeOptions; use crate::db_service::{ BeamlineConfiguration, BeamlineConfigurationUpdate, SqliteScanPathService, }; +use crate::db_service::error::ConfigurationError; use crate::numtracker::GdaNumTracker; use crate::paths::{ BeamlineField, DetectorField, DetectorTemplate, PathSpec, ScanField, ScanTemplate, @@ -207,6 +208,10 @@ impl ScanPaths { #[Object] impl BeamlineConfiguration { + pub async fn instrument(&self) -> async_graphql::Result { + Ok(self.name().to_owned()) + } + pub async fn visit_template(&self) -> async_graphql::Result { Ok(self.visit()?.to_string()) } @@ -255,14 +260,27 @@ impl Query { } #[instrument(skip(self, ctx))] - async fn configuration( + async fn configurations( &self, ctx: &Context<'_>, - beamline: String, - ) -> async_graphql::Result { + beamline_filter: Option, + ) -> async_graphql::Result> { let db = ctx.data::()?; - trace!("Getting config for {beamline:?}"); - Ok(db.current_configuration(&beamline).await?) + let matching = match beamline_filter { + Some(filter) => { + trace!("Getting configs matching {filter:?}"); + match db.current_configuration(&filter).await { + Ok(configuration) => vec![configuration], + Err(ConfigurationError::MissingBeamline(_)) => vec![], + Err(other) => Err(other)? + } + } + None => { + trace!("Getting all configs"); + db.configurations().await? + } + }; + Ok(matching) } }