diff --git a/server/src/config.rs b/server/src/config.rs index f61df14..4e71103 100644 --- a/server/src/config.rs +++ b/server/src/config.rs @@ -37,7 +37,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { - log::warn!("(Config default) Creating Config object with default values."); + log::warn!("(default) Creating Config object with default values."); Self::new() } } diff --git a/server/src/grpc/api/mod.rs b/server/src/grpc/api/mod.rs index 4a2d622..2ec04b4 100644 --- a/server/src/grpc/api/mod.rs +++ b/server/src/grpc/api/mod.rs @@ -34,7 +34,7 @@ pub fn unconfirmed_flight_plans() -> &'static Mutex Option> { let Ok(itineraries) = unconfirmed_itineraries().lock() else { - grpc_error!("(get_draft_itinerary_by_id) mutex Lock Error getting itinerary from temp storage"); + grpc_error!("(get_draft_itinerary_by_id) mutex Lock Error getting itinerary from temp storage."); return None; }; @@ -44,7 +44,7 @@ pub fn get_draft_itinerary_by_id(id: &str) -> Option> { /// Gets flight plan from hash map of unconfirmed flight plans pub fn get_draft_fp_by_id(id: &str) -> Option { let Ok(flight_plans) = unconfirmed_flight_plans().lock() else { - grpc_error!("(get_draft_fp_by_id) mutex Lock Error getting flight plan from temp storage"); + grpc_error!("(get_draft_fp_by_id) mutex Lock Error getting flight plan from temp storage."); return None; }; diff --git a/server/src/grpc/api/query_flight.rs b/server/src/grpc/api/query_flight.rs index dda50ee..7141cb5 100644 --- a/server/src/grpc/api/query_flight.rs +++ b/server/src/grpc/api/query_flight.rs @@ -23,6 +23,7 @@ pub const LANDING_AND_UNLOADING_TIME_SECONDS: i64 = 600; pub const MAX_FLIGHT_QUERY_WINDOW_MINUTES: i64 = 360; // +/- 3 hours (6 total) /// Sanitized version of the gRPC query +#[derive(Debug)] struct FlightQuery { departure_vertiport_id: String, arrival_vertiport_id: String, @@ -33,7 +34,7 @@ struct FlightQuery { } /// Error type for FlightQuery -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] enum FlightQueryError { InvalidVertiportId, InvalidTime, @@ -54,13 +55,13 @@ impl TryFrom for FlightQuery { type Error = FlightQueryError; fn try_from(request: QueryFlightRequest) -> Result { - const ERROR_PREFIX: &str = "(TryFrom FlightQuery)"; + const ERROR_PREFIX: &str = "(try_from)"; let departure_vertiport_id = match Uuid::parse_str(&request.vertiport_depart_id) { Ok(id) => id.to_string(), _ => { grpc_error!( - "(FlightQuery::TryFrom) {} Invalid departure vertiport ID: {}", + "{} Invalid departure vertiport ID: {}", ERROR_PREFIX, request.vertiport_depart_id ); @@ -72,7 +73,7 @@ impl TryFrom for FlightQuery { Ok(id) => id.to_string(), _ => { grpc_error!( - "(FlightQuery::TryFrom) {} Invalid departure vertiport ID: {}", + "{} Invalid departure vertiport ID: {}", ERROR_PREFIX, request.vertiport_arrive_id ); @@ -81,12 +82,12 @@ impl TryFrom for FlightQuery { }; let Some(latest_arrival_time) = request.latest_arrival_time.clone() else { - grpc_warn!("(FlightQuery::TryFrom) {} latest arrival time not provided.", ERROR_PREFIX); + grpc_warn!("{} latest arrival time not provided.", ERROR_PREFIX); return Err(FlightQueryError::InvalidTime); }; let Some(earliest_departure_time) = request.earliest_departure_time else { - grpc_warn!("(FlightQuery::TryFrom) {} earliest departure time not provided.", ERROR_PREFIX); + grpc_warn!("{} earliest departure time not provided.", ERROR_PREFIX); return Err(FlightQueryError::InvalidTime); }; @@ -95,7 +96,7 @@ impl TryFrom for FlightQuery { if earliest_departure_time > latest_arrival_time { grpc_warn!( - "(FlightQuery::TryFrom) {} earliest departure time is after latest arrival time.", + "{} earliest departure time is after latest arrival time.", ERROR_PREFIX ); return Err(FlightQueryError::InvalidTime); @@ -106,18 +107,12 @@ impl TryFrom for FlightQuery { if latest_arrival_time - earliest_departure_time > Duration::minutes(MAX_FLIGHT_QUERY_WINDOW_MINUTES) { - grpc_warn!( - "(FlightQuery::TryFrom) {} time range too large.", - ERROR_PREFIX - ); + grpc_warn!("{} time range too large.", ERROR_PREFIX); return Err(FlightQueryError::TimeRangeTooLarge); } if latest_arrival_time < Utc::now() { - grpc_warn!( - "(FlightQuery::TryFrom) {} latest arrival time is in the past.", - ERROR_PREFIX - ); + grpc_warn!("{} latest arrival time is in the past.", ERROR_PREFIX); return Err(FlightQueryError::InvalidTime); } @@ -307,304 +302,91 @@ pub async fn query_flight( #[cfg(test)] #[cfg(feature = "stub_backends")] mod tests { - // use crate::test_util::{ensure_storage_mock_data, get_vertiports_from_storage}; - // use crate::{init_logger, Config}; - - // use super::*; - // use chrono::{TimeZone, Utc}; - - // #[tokio::test] - // async fn test_get_sorted_flight_plans() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_get_sorted_flight_plans) start"); - // ensure_storage_mock_data().await; - // let clients = get_clients().await; - - // // our mock setup inserts only 3 flight_plans with an arrival date before "2022-10-26 14:30:00" - // let expected_number_returned = 3; - - // let res = get_sorted_flight_plans( - // &Utc.datetime_from_str("2022-10-26 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap(), - // &clients - // ).await; - // unit_test_debug!( - // "(test_get_sorted_flight_plans) flight_plans returned: {:#?}", - // res - // ); - - // assert!(res.is_ok()); - // assert_eq!(res.unwrap().len(), expected_number_returned); - // unit_test_info!("(test_get_sorted_flight_plans) success"); - // } - - // #[tokio::test] - // async fn test_query_flight() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_query_flight) start"); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-25 11:20:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-25 12:15:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[0].id.clone(), - // vertiport_arrive_id: vertiports[1].id.clone(), - // })) - // .await; - // unit_test_debug!("(test_query_flight) query_flight result: {:?}", res); - // assert!(res.is_ok()); - // assert_eq!(res.unwrap().into_inner().itineraries.len(), 5); - // unit_test_info!("(test_query_flight) success"); - // } - - // ///4. destination vertiport is available for about 15 minutes, no other restrictions - // /// - returns 2 flights (assuming 10 minutes needed for unloading, this can fit 2 flights - // /// if first is exactly at the beginning of 15 minute gap and second is exactly after 5 minutes) - // #[tokio::test] - // async fn test_query_flight_4_dest_vertiport_tight_availability_should_return_two_flights() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_query_flight_4_dest_vertiport_tight_availability_should_return_two_flights) start"); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-25 14:20:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-25 15:10:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[2].id.clone(), - // vertiport_arrive_id: vertiports[1].id.clone(), - // })) - // .await - // .unwrap(); - - // unit_test_debug!("(test_query_flight_4_dest_vertiport_tight_availability_should_return_two_flights) query_flight result: {:#?}", res); - // assert_eq!(res.into_inner().itineraries.len(), 2); - // unit_test_info!("(test_query_flight_4_dest_vertiport_tight_availability_should_return_two_flights) success"); - // } - - // ///5. source or destination vertiport doesn't have any vertipad free for the time range - // ///no flight plans returned - // #[tokio::test] - // async fn test_query_flight_5_dest_vertiport_no_availability_should_return_zero_flights() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!( - // "(test_query_flight_5_dest_vertiport_no_availability_should_return_zero_flights) start" - // ); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-26 14:00:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-26 14:40:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[1].id.clone(), - // vertiport_arrive_id: vertiports[0].id.clone(), - // })) - // .await; - - // unit_test_debug!("(test_query_flight_5_dest_vertiport_no_availability_should_return_zero_flights) query_flight result: {:#?}", res); - // assert_eq!( - // res.unwrap_err() - // .message() - // .contains("No flight plans available"), - // true - // ); - // unit_test_info!( - // "(test_query_flight_5_dest_vertiport_no_availability_should_return_zero_flights) success" - // ); - // } - - // ///6. vertiports are available but aircraft are not at the vertiport for the requested time - // /// but at least one aircraft is IN FLIGHT to requested vertiport for that time and has availability for a next flight. - // /// - skips all unavailable time slots (4) and returns only time slots from when aircraft is available (1) - // #[tokio::test] - // async fn test_query_flight_6_no_aircraft_at_vertiport() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_query_flight_6_no_aircraft_at_vertiport) start"); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-26 14:15:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-26 15:00:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[0].id.clone(), - // vertiport_arrive_id: vertiports[2].id.clone(), - // })) - // .await - // .unwrap() - // .into_inner(); - - // unit_test_debug!( - // "(test_query_flight_6_no_aircraft_at_vertiport) query_flight result: {:#?}", - // res - // ); - // assert_eq!(res.itineraries.len(), 1); - // assert_eq!(res.itineraries[0].flight_plans.len(), 1); - // unit_test_info!("(test_query_flight_6_no_aircraft_at_vertiport) success"); - // } - - // /// 7. vertiports are available but aircraft are not at the vertiport for the requested time - // /// but at least one aircraft is PARKED at other vertiport for the "requested time - N minutes" - // #[tokio::test] - // async fn test_query_flight_7_deadhead_flight_of_parked_vehicle() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_query_flight_7_deadhead_flight_of_parked_vehicle) start"); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-26 16:00:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-26 16:30:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[2].id.clone(), - // vertiport_arrive_id: vertiports[0].id.clone(), - // })) - // .await - // .unwrap() - // .into_inner(); - - // unit_test_debug!( - // "(test_query_flight_7_deadhead_flight_of_parked_vehicle) query_flight result: {:#?}", - // res - // ); - // assert_eq!(res.itineraries.len(), 1); - // assert_eq!(res.itineraries[0].flight_plans.len(), 2); - // unit_test_info!("(test_query_flight_7_deadhead_flight_of_parked_vehicle) success"); - // } - - // /// 8. vertiports are available but aircraft are not at the vertiport for the requested time - // /// but at least one aircraft is EN ROUTE to another vertiport for the "requested time - N minutes - M minutes" - // #[tokio::test] - // async fn test_query_flight_8_deadhead_flight_of_in_flight_vehicle() { - // init_logger(&Config::try_from_env().unwrap_or_default()); - // unit_test_info!("(test_query_flight_8_deadhead_flight_of_in_flight_vehicle) start"); - // ensure_storage_mock_data().await; - - // let vertiports = get_vertiports_from_storage().await; - // let res = query_flight(Request::new(QueryFlightRequest { - // is_cargo: false, - // persons: None, - // weight_grams: None, - // earliest_departure_time: Some( - // Utc.datetime_from_str("2022-10-27 12:30:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // latest_arrival_time: Some( - // Utc.datetime_from_str("2022-10-27 13:30:00", "%Y-%m-%d %H:%M:%S") - // .unwrap() - // .into(), - // ), - // vertiport_depart_id: vertiports[1].id.clone(), - // vertiport_arrive_id: vertiports[0].id.clone(), - // })) - // .await - // .unwrap() - // .into_inner(); - - // unit_test_debug!( - // "(test_query_flight_8_deadhead_flight_of_in_flight_vehicle) query_flight result: {:#?}", - // res - // ); - // assert_eq!(res.itineraries.len(), 2); - // assert_eq!(res.itineraries[0].flight_plans.len(), 2); - // unit_test_info!("(test_query_flight_8_deadhead_flight_of_in_flight_vehicle) success"); - // } - - /* TODO: R4 refactor code and re-implement this test - /// 9. destination vertiport is not available because of capacity - /// - if at requested time all pads are occupied and at least one is parked (not loading/unloading), - /// a extra flight plan should be created to move idle aircraft to the nearest unoccupied vertiport - /// (or to preferred vertiport in hub and spoke model). + use crate::test_util::{ensure_storage_mock_data, get_vertiports_from_storage}; + use crate::{init_logger, Config}; + + use super::*; + use chrono::{TimeZone, Utc}; + #[tokio::test] - async fn test_query_flight_9_deadhead_destination_flight_no_capacity_at_destination_vertiport() - { + async fn test_get_sorted_flight_plans() { init_logger(&Config::try_from_env().unwrap_or_default()); - unit_test_info!("(test_query_flight_9_deadhead_destination_flight_no_capacity_at_destination_vertiport) start"); + unit_test_info!("(test_get_sorted_flight_plans) start"); ensure_storage_mock_data().await; - init_router().await; + let clients = get_clients().await; - let vertiports = get_vertiports_from_storage().await; - let res = query_flight(Request::new(QueryFlightRequest { - is_cargo: false, - persons: None, - weight_grams: None, - earliest_departure_time: Some( - Utc.datetime_from_str("2022-10-27 15:10:00", "%Y-%m-%d %H:%M:%S") - .unwrap() - .into(), - ), - latest_arrival_time: Some( - Utc.datetime_from_str("2022-10-27 16:00:00", "%Y-%m-%d %H:%M:%S") - .unwrap() - .into(), - ), - vertiport_depart_id: vertiports[1].id.clone(), - vertiport_arrive_id: vertiports[3].id.clone(), - })) - .await - .unwrap() - .into_inner(); + // our mock setup inserts only 3 flight_plans with an arrival date before "2022-10-26 14:30:00" + let expected_number_returned = 3; + + let chrono::LocalResult::Single(date) = Utc.with_ymd_and_hms(2022, 10, 26, 14, 30, 0) else { + panic!(); + }; + let res = get_sorted_flight_plans(&date, &clients).await; unit_test_debug!( - "(test_query_flight_9_deadhead_destination_flight_no_capacity_at_destination_vertiport) query_flight result: {:#?}", + "(test_get_sorted_flight_plans) flight_plans returned: {:#?}", res ); - assert_eq!(res.itineraries.len(), 1); - assert_eq!(res.itineraries[0].deadhead_flight_plans.len(), 1); - unit_test_info!("(test_query_flight_9_deadhead_destination_flight_no_capacity_at_destination_vertiport) success"); + + assert!(res.is_ok()); + assert_eq!(res.unwrap().len(), expected_number_returned); + unit_test_info!("(test_get_sorted_flight_plans) success"); + } + + #[tokio::test] + #[cfg(feature = "stub_backends")] + async fn test_query_invalid() { + init_logger(&Config::try_from_env().unwrap_or_default()); + + let vertiports = get_vertiports_from_storage().await; + let mut query = QueryFlightRequest { + is_cargo: true, + persons: None, + weight_grams: Some(10), + earliest_departure_time: None, + latest_arrival_time: None, + vertiport_depart_id: vertiports[0].id.clone(), + vertiport_arrive_id: vertiports[1].id.clone(), + }; + + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::InvalidTime); + + // latest arrival time is less than earliest departure time + query.earliest_departure_time = Some((Utc::now() + Duration::hours(4)).into()); + query.latest_arrival_time = Some((Utc::now() + Duration::hours(1)).into()); + + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::InvalidTime); + + // latest arrival time is in the past + query.latest_arrival_time = Some((Utc::now() - Duration::seconds(1)).into()); + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::InvalidTime); + + // Too large of a time range + query.earliest_departure_time = Some(Utc::now().into()); + query.latest_arrival_time = + Some((Utc::now() + Duration::minutes(MAX_FLIGHT_QUERY_WINDOW_MINUTES + 1)).into()); + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::TimeRangeTooLarge); + + query.earliest_departure_time = Some(Utc::now().into()); + query.latest_arrival_time = + Some((Utc::now() + Duration::minutes(MAX_FLIGHT_QUERY_WINDOW_MINUTES - 1)).into()); + FlightQuery::try_from(query.clone()).unwrap(); + + // Invalid vertiport IDs + query.vertiport_depart_id = "invalid".to_string(); + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::InvalidVertiportId); + + query.vertiport_depart_id = Uuid::new_v4().to_string(); + query.vertiport_arrive_id = "invalid".to_string(); + let e = FlightQuery::try_from(query.clone()).unwrap_err(); + assert_eq!(e, FlightQueryError::InvalidVertiportId); + + query.vertiport_arrive_id = Uuid::new_v4().to_string(); + FlightQuery::try_from(query.clone()).unwrap(); } - */ } diff --git a/server/src/lib.rs b/server/src/lib.rs index 6aef7e9..83319a2 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,7 +18,7 @@ pub fn init_logger(config: &Config) { let log_cfg: &str = config.log_config.as_str(); if let Err(e) = log4rs::init_file(log_cfg, Default::default()) { panic!( - "(logger) could not parse log config {} found in config {:?}: {}.", + "(init_logger) could not parse log config {} found in config {:?}: {}.", log_cfg, config, e ); } diff --git a/server/src/main.rs b/server/src/main.rs index 8302b9c..35ed3d4 100755 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -6,7 +6,7 @@ use svc_scheduler::*; #[tokio::main] #[cfg(not(tarpaulin_include))] async fn main() -> Result<(), Box> { - println!("(svc-scheduler) server startup."); + println!("(main) server startup."); // Will use default config settings if no environment vars are found. let config = Config::try_from_env().unwrap_or_default(); @@ -19,7 +19,7 @@ async fn main() -> Result<(), Box> { // Make sure all log message are written/ displayed before shutdown log::logger().flush(); - info!("(svc-scheduler) server shutdown."); + info!("(main) server shutdown."); Ok(()) } diff --git a/server/src/router/flight_plan.rs b/server/src/router/flight_plan.rs index 398e28a..0b26c63 100644 --- a/server/src/router/flight_plan.rs +++ b/server/src/router/flight_plan.rs @@ -38,7 +38,7 @@ impl TryFrom for FlightPlanSchedule { fn try_from(flight_plan: flight_plan::Object) -> Result { let Some(data) = flight_plan.data else { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no data.", + "(try_from) Flight plan [{}] has no data.", flight_plan.id ); return Err(FlightPlanError::InvalidData) @@ -51,7 +51,7 @@ impl TryFrom for FlightPlanSchedule { Some(departure_time) => departure_time.into(), None => { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no scheduled departure.", + "(try_from) Flight plan [{}] has no scheduled departure.", flight_plan.id ); return Err(FlightPlanError::InvalidData); @@ -62,7 +62,7 @@ impl TryFrom for FlightPlanSchedule { Some(arrival_time) => arrival_time.into(), None => { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no scheduled arrival.", + "(try_from) Flight plan [{}] has no scheduled arrival.", flight_plan.id ); return Err(FlightPlanError::InvalidData); @@ -74,7 +74,7 @@ impl TryFrom for FlightPlanSchedule { // let Some(departure_vertiport_id) = data.departure_vertiport_id else { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no departure vertiport.", + "(try_from) Flight plan [{}] has no departure vertiport.", flight_plan.id ); return Err(FlightPlanError::InvalidData) @@ -84,7 +84,7 @@ impl TryFrom for FlightPlanSchedule { Ok(id) => id.to_string(), Err(e) => { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has invalid departure vertiport id: {}", + "(try_from) Flight plan [{}] has invalid departure vertiport id: {}", flight_plan.id, e ); @@ -94,7 +94,7 @@ impl TryFrom for FlightPlanSchedule { let Some(arrival_vertiport_id) = data.destination_vertiport_id else { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no arrival vertiport.", + "(try_from) Flight plan [{}] has no arrival vertiport.", flight_plan.id ); return Err(FlightPlanError::InvalidData) @@ -104,7 +104,7 @@ impl TryFrom for FlightPlanSchedule { Ok(id) => id.to_string(), Err(e) => { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has invalid arrival vertiport id: {}", + "(try_from) Flight plan [{}] has invalid arrival vertiport id: {}", flight_plan.id, e ); @@ -117,7 +117,7 @@ impl TryFrom for FlightPlanSchedule { // let Ok(vehicle_id) = Uuid::parse_str(&data.vehicle_id) else { router_error!( - "(get_flight_plan_schedule) Flight plan [{}] has no vehicle.", + "(try_from) Flight plan [{}] has no vehicle.", flight_plan.id ); return Err(FlightPlanError::InvalidData) diff --git a/server/src/router/itinerary.rs b/server/src/router/itinerary.rs index 8fd1987..6d0201a 100644 --- a/server/src/router/itinerary.rs +++ b/server/src/router/itinerary.rs @@ -81,9 +81,7 @@ pub async fn get_itineraries( Ok(itinerary) => itineraries.push(itinerary), Err(ItineraryError::ClientError) => { // exit immediately if svc-gis is down, don't allow new flights - router_error!( - "(get_vehicle_availability) Could not determine path; client error." - ); + router_error!("(get_itineraries) Could not determine path; client error."); return Err(ItineraryError::ClientError); } _ => { @@ -126,7 +124,7 @@ async fn aircraft_selection( } Err(ItineraryError::ClientError) => { // exit immediately if svc-gis is down, don't allow new flights - router_error!("(get_vehicle_availability) Could not determine path; client error."); + router_error!("(aircraft_selection) Could not determine path; client error."); return Err(ItineraryError::ClientError); } _ => { @@ -152,7 +150,7 @@ async fn get_itinerary( // Must be some overlap between the flight window and the available timeslot let Ok(overlap) = availability.timeslot.overlap(flight_window) else { router_debug!( - "(is_aircraft_available) No overlap between flight window and available timeslot." + "(get_itinerary) No overlap between flight window and available timeslot." ); return Err(ItineraryError::ScheduleConflict); @@ -160,7 +158,7 @@ async fn get_itinerary( let Some(ref departure_vertiport_id) = flight_plan.departure_vertiport_id else { router_error!( - "(get_vehicle_itinerary) Flight plan doesn't have departure_vertiport_id.", + "(get_itinerary) Flight plan doesn't have departure_vertiport_id.", ); return Err(ItineraryError::InvalidData); @@ -168,7 +166,7 @@ async fn get_itinerary( let Some(ref arrival_vertiport_id) = flight_plan.destination_vertiport_id else { router_error!( - "(get_vehicle_itinerary) Flight plan doesn't have destination_vertiport_id.", + "(get_itinerary) Flight plan doesn't have destination_vertiport_id.", ); return Err(ItineraryError::InvalidData); @@ -199,7 +197,7 @@ async fn get_itinerary( // is blocking journeys from this depart timeslot // Break out and try the next depart timeslot router_debug!( - "(get_vehicle_availability) No path found from vertiport {} + "(get_itinerary) No path found from vertiport {} to vertiport {} (from {} to {}).", availability.vertiport_id, departure_vertiport_id, @@ -211,7 +209,7 @@ async fn get_itinerary( } Err(BestPathError::ClientError) => { // exit immediately if svc-gis is down, don't allow new flights - router_error!("(get_vehicle_availability) Could not determine path."); + router_error!("(get_itinerary) Could not determine path."); return Err(ItineraryError::ClientError); } }; @@ -227,9 +225,7 @@ async fn get_itinerary( if scheduled_arrival > availability.timeslot.time_end { // This flight plan would end after the available timeslot // Break out and try the next available timeslot - router_debug!( - "(get_vehicle_availability) Flight plan would end after available timeslot." - ); + router_debug!("(get_itinerary) Flight plan would end after available timeslot."); return Err(ItineraryError::ScheduleConflict); } @@ -257,9 +253,7 @@ async fn get_itinerary( Some(last) => match &last.scheduled_arrival { Some(s) => s.clone().into(), None => { - router_error!( - "(get_vehicle_availability) Last flight plan has no scheduled arrival." - ); + router_error!("(get_itinerary) Last flight plan has no scheduled arrival."); return Err(ItineraryError::InvalidData); } @@ -272,9 +266,7 @@ async fn get_itinerary( if scheduled_arrival > availability.timeslot.time_end { // This flight plan would end after the available timeslot // Break out and try the next available timeslot - router_debug!( - "(get_vehicle_availability) Flight plan would end after available timeslot." - ); + router_debug!("(get_itinerary) Flight plan would end after available timeslot."); return Err(ItineraryError::ScheduleConflict); } @@ -282,7 +274,7 @@ async fn get_itinerary( if scheduled_arrival > flight_window.time_end { // This flight plan would end after the flight window // Break out and try the next available timeslot - router_debug!("(get_vehicle_availability) Flight plan would end after flight window."); + router_debug!("(get_itinerary) Flight plan would end after flight window."); return Err(ItineraryError::ScheduleConflict); } @@ -303,7 +295,7 @@ async fn get_itinerary( // right now it boomerangs back to its original last_vertiport_id let Some(last) = flight_plans.last() else { router_error!( - "(get_vehicle_availability) No flight plans found for vehicle {}.", + "(get_itinerary) No flight plans found for vehicle {}.", vehicle_id ); @@ -312,7 +304,7 @@ async fn get_itinerary( let Some(last_arrival) = &last.scheduled_arrival else { router_error!( - "(get_vehicle_availability) Last flight plan has no scheduled arrival." + "(get_itinerary) Last flight plan has no scheduled arrival." ); return Err(ItineraryError::InvalidData); @@ -336,7 +328,7 @@ async fn get_itinerary( // is blocking journeys from this depart timeslot // Break out and try the next depart timeslot router_debug!( - "(get_vehicle_availability) No path found from vertiport {} + "(get_itinerary) No path found from vertiport {} to vertiport {} (from {} to {}).", arrival_vertiport_id, availability.vertiport_id, @@ -348,7 +340,7 @@ async fn get_itinerary( } Err(BestPathError::ClientError) => { // exit immediately if svc-gis is down, don't allow new flights - router_error!("(get_vehicle_availability) Could not determine path."); + router_error!("(get_itinerary) Could not determine path."); return Err(ItineraryError::ClientError); } }; @@ -360,9 +352,7 @@ async fn get_itinerary( if scheduled_arrival > availability.timeslot.time_end { // This flight plan would end after the available timeslot // Break out and try the next available timeslot - router_debug!( - "(get_vehicle_availability) Flight plan would end after available timeslot." - ); + router_debug!("(get_itinerary) Flight plan would end after available timeslot."); return Err(ItineraryError::ScheduleConflict); } diff --git a/server/src/router/schedule.rs b/server/src/router/schedule.rs index 9cbdeee..7327f76 100644 --- a/server/src/router/schedule.rs +++ b/server/src/router/schedule.rs @@ -129,11 +129,7 @@ impl Sub for Timeslot { }]; } - router_warn!( - "(timeslot_collision) Unhandled case: {:?} {:?}", - self, - other - ); + router_warn!("(sub) Unhandled case: {:?} {:?}", self, other); vec![] } @@ -207,22 +203,22 @@ impl FromStr for Calendar { /// "DTSTART:20221020T180000Z;DURATION:PT1H" not "DURATION:PT1H;DTSTART:20221020T180000Z" /// Duration is in ISO8601 format (`iso8601_duration` crate) fn from_str(calendar_str: &str) -> Result { - router_debug!("(Calendar from_str) Parsing calendar: {}", calendar_str); + router_debug!("(from_str) Parsing calendar: {}", calendar_str); let rrule_sets: Vec<&str> = calendar_str .split("DTSTART:") .filter(|s| !s.is_empty()) .collect(); - router_debug!("(Calendar from_str) rrule_sets: {:?}", rrule_sets); + router_debug!("(from_str) rrule_sets: {:?}", rrule_sets); let mut recurrent_events: Vec = Vec::new(); for rrule_set_str in rrule_sets { - router_debug!("(Calendar from_str) rrule_set_str: {}", rrule_set_str); + router_debug!("(from_str) rrule_set_str: {}", rrule_set_str); let rrules_with_header: Vec<&str> = rrule_set_str .split('\n') .filter(|s| !s.is_empty()) .collect(); if rrules_with_header.len() < 2 { router_error!( - "(Calendar from_str) Invalid rrule {} with header length: {}", + "(from_str) Invalid rrule {} with header length: {}", calendar_str, rrules_with_header.len() ); @@ -236,7 +232,7 @@ impl FromStr for Calendar { .collect(); if header_parts.len() != 2 { router_error!( - "(Calendar from_str) Invalid header parts length: {}", + "(from_str) Invalid header parts length: {}", header_parts.len() ); return Err(CalendarError::HeaderPartsLength); @@ -245,12 +241,12 @@ impl FromStr for Calendar { let dtstart = header_parts[0]; let duration: &str = header_parts[1]; let Ok(duration) = duration.parse::() else { - router_error!("(Calendar from_str) Invalid duration: {:?}", duration); + router_error!("(from_str) Invalid duration: {:?}", duration); return Err(CalendarError::Duration); }; let Some(duration) = duration.to_chrono() else { - router_error!("(Calendar from_str) Could not convert duration to chrono::DateTime: {:?}", duration); + router_error!("(from_str) Could not convert duration to chrono::DateTime: {:?}", duration); return Err(CalendarError::Duration); }; @@ -258,7 +254,7 @@ impl FromStr for Calendar { let rrset_res = RRuleSet::from_str(&str); let Ok(rrule_set) = rrset_res else { - router_error!("(Calendar from_str) Invalid rrule set: {:?}", rrset_res.unwrap_err()); + router_error!("(from_str) Invalid rrule set: {:?}", rrset_res.unwrap_err()); return Err(CalendarError::RruleSet); }; @@ -267,10 +263,7 @@ impl FromStr for Calendar { duration, }); } - router_debug!( - "(Calendar from_str) Parsed calendar: {:?}", - recurrent_events - ); + router_debug!("(from_str) Parsed calendar: {:?}", recurrent_events); Ok(Calendar { events: recurrent_events, }) diff --git a/server/src/router/vehicle.rs b/server/src/router/vehicle.rs index 1c472d7..84824d7 100644 --- a/server/src/router/vehicle.rs +++ b/server/src/router/vehicle.rs @@ -87,11 +87,7 @@ impl TryFrom for Aircraft { let vehicle_uuid = match Uuid::parse_str(&vehicle.id) { Ok(uuid) => uuid.to_string(), Err(e) => { - router_error!( - "(Aircraft::try_from) Vehicle {} has invalid UUID: {}", - vehicle.id, - e - ); + router_error!("(try_from) Vehicle {} has invalid UUID: {}", vehicle.id, e); return Err(VehicleError::InvalidData); } @@ -99,7 +95,7 @@ impl TryFrom for Aircraft { let Some(data) = vehicle.data else { router_error!( - "(Aircraft::try_from) Vehicle doesn't have data: {:?}", + "(try_from) Vehicle doesn't have data: {:?}", vehicle ); @@ -108,7 +104,7 @@ impl TryFrom for Aircraft { let Some(last_vertiport_id) = data.last_vertiport_id else { router_error!( - "(Aircraft::try_from) Vehicle {} doesn't have last_vertiport_id.", + "(try_from) Vehicle {} doesn't have last_vertiport_id.", vehicle_uuid ); @@ -119,7 +115,7 @@ impl TryFrom for Aircraft { Ok(uuid) => uuid.to_string(), Err(e) => { router_error!( - "(Aircraft::try_from) Vehicle {} has invalid last_vertiport_id: {}", + "(try_from) Vehicle {} has invalid last_vertiport_id: {}", vehicle_uuid, e ); @@ -137,7 +133,7 @@ impl TryFrom for Aircraft { let Ok(vehicle_calendar) = Calendar::from_str(&calendar) else { router_debug!( - "(is_vehicle_available) Invalid schedule for vehicle {}: {}", + "(try_from) Invalid schedule for vehicle {}: {}", vehicle_uuid, calendar ); @@ -162,12 +158,14 @@ async fn get_aircraft(clients: &GrpcClients) -> Result, VehicleErr // disabled aircraft // TODO(R4): Ignore aircraft that haven't been updated recently - let mut filter = AdvancedSearchFilter::default(); - // We should further limit this, but for now we'll just get all aircraft // Need something to sort by, ascending distance from the // departure vertiport or charge level before cutting off the list - filter.results_per_page = 1000; + let filter = AdvancedSearchFilter { + results_per_page: 1000, + ..Default::default() + }; + let Ok(response) = clients .storage .vehicle @@ -190,12 +188,12 @@ async fn get_aircraft(clients: &GrpcClients) -> Result, VehicleErr /// Estimate should be rather generous to block resources instead of potentially overloading them pub fn estimate_flight_time_seconds(distance_meters: &f32) -> Duration { router_debug!( - "(estimate_flight_time_minutes) distance_meters: {}", + "(estimate_flight_time_seconds) distance_meters: {}", *distance_meters ); let aircraft = AircraftType::Cargo; // TODO(R4): Hardcoded for demo - router_debug!("(estimate_flight_time_minutes) aircraft: {:?}", aircraft); + router_debug!("(estimate_flight_time_seconds) aircraft: {:?}", aircraft); match aircraft { AircraftType::Cargo => { @@ -269,7 +267,7 @@ pub async fn get_aircraft_gaps( schedule.push(fp.clone()); } else { router_warn!( - "(query_flight) Flight plan for unknown aircraft: {}", + "(get_aircraft_gaps) Flight plan for unknown aircraft: {}", fp.vehicle_id ); } @@ -280,7 +278,7 @@ pub async fn get_aircraft_gaps( for vehicle in aircraft.into_iter() { let Some(schedule) = aircraft_schedules.get_mut(&vehicle.vehicle_uuid) else { router_warn!( - "(query_flight) Flight plan for unknown aircraft: {}", + "(get_aircraft_gaps) Flight plan for unknown aircraft: {}", vehicle.vehicle_uuid );