diff --git a/emgauwa-controller/src/main.rs b/emgauwa-controller/src/main.rs index 20bd992..308bf4d 100644 --- a/emgauwa-controller/src/main.rs +++ b/emgauwa-controller/src/main.rs @@ -3,6 +3,7 @@ use std::str; use crate::relay_loop::run_relay_loop; use crate::settings::Settings; use emgauwa_lib::db::{DbController, DbRelay}; +use emgauwa_lib::models::convert_db_list; use emgauwa_lib::types::ControllerUid; use emgauwa_lib::{db, models}; use futures::channel::mpsc; @@ -88,10 +89,7 @@ async fn main() { .await .unwrap(); - let relays = db_relays - .into_iter() - .map(|relay| models::Relay::from_db_relay(relay, &mut conn)) - .collect(); + let relays = convert_db_list(&mut conn, db_relays).expect("Failed to convert relays"); let this = models::Controller { controller: db_controller, diff --git a/emgauwa-controller/src/relay_loop.rs b/emgauwa-controller/src/relay_loop.rs index d961879..7a1e2ea 100644 --- a/emgauwa-controller/src/relay_loop.rs +++ b/emgauwa-controller/src/relay_loop.rs @@ -1,8 +1,15 @@ use crate::settings::Settings; use chrono::Local; +use std::time::Duration; +use tokio::time; #[allow(unused_variables)] pub async fn run_relay_loop(settings: Settings) { - let next_timestamp = Local::now().naive_local(); - loop {} + let default_duration = Duration::from_millis(1000); + loop { + // naivetime timestamp for now + let next_timestamp = Local::now().naive_local().time() + default_duration; + time::sleep(default_duration).await; + println!("Relay loop: {}", next_timestamp) + } } diff --git a/emgauwa-lib/src/handlers/v1/relays.rs b/emgauwa-lib/src/handlers/v1/relays.rs index 2f7e69a..457d66b 100644 --- a/emgauwa-lib/src/handlers/v1/relays.rs +++ b/emgauwa-lib/src/handlers/v1/relays.rs @@ -6,7 +6,7 @@ use sqlx::{Pool, Sqlite}; use crate::db::DbRelay; use crate::handlers::errors::ApiError; -use crate::models::Relay; +use crate::models::{convert_db_list, Relay}; #[derive(Debug, Serialize, Deserialize)] pub struct RequestRelay { @@ -18,14 +18,11 @@ pub struct RequestRelay { pub async fn index(pool: web::Data>) -> Result { let mut pool_conn = pool.acquire().await?; - let relays = DbRelay::get_all(&mut pool_conn).await?; + let db_relays = DbRelay::get_all(&mut pool_conn).await?; - let return_relays: Vec = relays - .into_iter() - .map(|s| Relay::from_db_relay(s, &mut pool_conn)) - .collect(); + let relays: Vec = convert_db_list(&mut pool_conn, db_relays)?; - Ok(HttpResponse::Ok().json(return_relays)) + Ok(HttpResponse::Ok().json(relays)) } //#[get("/api/v1/tags/tag/{tag}")] diff --git a/emgauwa-lib/src/handlers/v1/schedules.rs b/emgauwa-lib/src/handlers/v1/schedules.rs index 14d4949..b0f5afd 100644 --- a/emgauwa-lib/src/handlers/v1/schedules.rs +++ b/emgauwa-lib/src/handlers/v1/schedules.rs @@ -7,7 +7,7 @@ use crate::db::errors::DatabaseError; use crate::db::DbTag; use crate::db::{DbPeriods, DbSchedule}; use crate::handlers::errors::ApiError; -use crate::models::Schedule; +use crate::models::{convert_db_list, FromDbModel, Schedule}; use crate::types::ScheduleUid; #[derive(Debug, Serialize, Deserialize)] @@ -21,14 +21,11 @@ pub struct RequestSchedule { pub async fn index(pool: web::Data>) -> Result { let mut pool_conn = pool.acquire().await?; - let schedules = DbSchedule::get_all(&mut pool_conn).await?; + let db_schedules = DbSchedule::get_all(&mut pool_conn).await?; - let return_schedules: Vec = schedules - .into_iter() - .map(|s| Schedule::from_schedule(s, &mut pool_conn)) - .collect(); + let schedules: Vec = convert_db_list(&mut pool_conn, db_schedules)?; - Ok(HttpResponse::Ok().json(return_schedules)) + Ok(HttpResponse::Ok().json(schedules)) } #[get("/api/v1/schedules/tag/{tag}")] @@ -43,14 +40,11 @@ pub async fn tagged( .await? .ok_or(DatabaseError::NotFound)?; - let schedules = DbSchedule::get_by_tag(&mut pool_conn, &tag_db).await?; + let db_schedules = DbSchedule::get_by_tag(&mut pool_conn, &tag_db).await?; - let return_schedules: Vec = schedules - .into_iter() - .map(|s| Schedule::from_schedule(s, &mut pool_conn)) - .collect(); + let schedules: Vec = convert_db_list(&mut pool_conn, db_schedules)?; - Ok(HttpResponse::Ok().json(return_schedules)) + Ok(HttpResponse::Ok().json(schedules)) } #[get("/api/v1/schedules/{schedule_id}")] @@ -67,7 +61,7 @@ pub async fn show( .await? .ok_or(DatabaseError::NotFound)?; - let return_schedule = Schedule::from_schedule(schedule, &mut pool_conn); + let return_schedule = Schedule::from_db_model(&mut pool_conn, schedule); Ok(HttpResponse::Ok().json(return_schedule)) } @@ -84,7 +78,7 @@ pub async fn add( .set_tags(&mut pool_conn, data.tags.as_slice()) .await?; - let return_schedule = Schedule::from_schedule(new_schedule, &mut pool_conn); + let return_schedule = Schedule::from_db_model(&mut pool_conn, new_schedule); Ok(HttpResponse::Created().json(return_schedule)) } @@ -109,24 +103,20 @@ pub async fn add_list( ) -> Result { let mut pool_conn = pool.acquire().await?; - let result: Vec> = data - .as_slice() - .iter() - .map(|request_schedule| { - futures::executor::block_on(add_list_single(&mut pool_conn, request_schedule)) - }) - .collect(); - - let mut return_schedules: Vec = Vec::new(); - for schedule in result { - match schedule { - Ok(schedule) => { - return_schedules.push(Schedule::from_schedule(schedule, &mut pool_conn)) + let mut db_schedules: Vec = Vec::new(); + data.iter().try_for_each(|s| { + let new_s = futures::executor::block_on(add_list_single(&mut pool_conn, s)); + match new_s { + Ok(new_s) => { + db_schedules.push(new_s); + Ok(()) } - Err(e) => return Ok(HttpResponse::from(e)), + Err(e) => Err(e), } - } - Ok(HttpResponse::Created().json(return_schedules)) + })?; + + let schedules: Vec = convert_db_list(&mut pool_conn, db_schedules)?; + Ok(HttpResponse::Created().json(schedules)) } #[put("/api/v1/schedules/{schedule_id}")] @@ -152,7 +142,7 @@ pub async fn update( .set_tags(&mut pool_conn, data.tags.as_slice()) .await?; - let return_schedule = Schedule::from_schedule(schedule, &mut pool_conn); + let return_schedule = Schedule::from_db_model(&mut pool_conn, schedule); Ok(HttpResponse::Ok().json(return_schedule)) } diff --git a/emgauwa-lib/src/models/mod.rs b/emgauwa-lib/src/models/mod.rs index fd23583..d719f64 100644 --- a/emgauwa-lib/src/models/mod.rs +++ b/emgauwa-lib/src/models/mod.rs @@ -1,20 +1,33 @@ use crate::db; +use crate::db::errors::DatabaseError; +use crate::db::{DbRelay, DbSchedule}; use futures::executor; use serde_derive::Serialize; use sqlx::pool::PoolConnection; use sqlx::Sqlite; +pub trait FromDbModel { + type DbModel: Clone; + + fn from_db_model( + conn: &mut PoolConnection, + db_model: Self::DbModel, + ) -> Result + where + Self: Sized; +} + #[derive(Serialize, Debug)] pub struct Schedule { #[serde(flatten)] - pub schedule: db::DbSchedule, + pub schedule: DbSchedule, pub tags: Vec, } #[derive(Serialize, Debug)] pub struct Relay { #[serde(flatten)] - pub relay: db::DbRelay, + pub relay: DbRelay, pub controller: db::DbController, pub tags: Vec, } @@ -26,25 +39,53 @@ pub struct Controller { pub relays: Vec, } -impl Schedule { - pub fn from_schedule(schedule: db::DbSchedule, conn: &mut PoolConnection) -> Self { - let schedule = schedule.clone(); - let tags = executor::block_on(schedule.get_tags(conn)).unwrap(); +impl FromDbModel for Schedule { + type DbModel = DbSchedule; - Schedule { schedule, tags } + fn from_db_model( + conn: &mut PoolConnection, + db_model: Self::DbModel, + ) -> Result { + let schedule = db_model.clone(); + let tags = executor::block_on(schedule.get_tags(conn))?; + + Ok(Schedule { schedule, tags }) } } -impl Relay { - pub fn from_db_relay(relay: db::DbRelay, conn: &mut PoolConnection) -> Self { - let relay = relay.clone(); - let controller = executor::block_on(relay.get_controller(conn)).unwrap(); - let tags = executor::block_on(relay.get_tags(conn)).unwrap(); +impl FromDbModel for Relay { + type DbModel = DbRelay; - Relay { + fn from_db_model( + conn: &mut PoolConnection, + db_model: Self::DbModel, + ) -> Result { + let relay = db_model.clone(); + let controller = executor::block_on(relay.get_controller(conn))?; + let tags = executor::block_on(relay.get_tags(conn))?; + + Ok(Relay { relay, controller, tags, - } + }) } } + +pub fn convert_db_list( + conn: &mut PoolConnection, + db_models: Vec, +) -> Result, DatabaseError> { + let mut result: Vec = Vec::new(); + db_models.into_iter().try_for_each(|s| { + let new = T::from_db_model(conn, s); + match new { + Ok(new) => { + result.push(new); + Ok(()) + } + Err(e) => Err(e), + } + })?; + Ok(result) +}