From dd850766fd2f2f29ec4b9ed11a0978bcf5161241 Mon Sep 17 00:00:00 2001 From: Tobias Reisinger <tobias@msrg.cc> Date: Wed, 24 Apr 2024 01:29:47 +0200 Subject: [PATCH] Add notification to controllers on schedule change --- Cargo.lock | 12 ++++++- emgauwa-core/Cargo.toml | 1 + emgauwa-core/src/handlers/v1/schedules.rs | 32 +++++++++++++++++-- emgauwa-lib/src/db/junction_relay_schedule.rs | 17 ++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b6ca2a..013c284 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -729,6 +729,7 @@ dependencies = [ "chrono", "emgauwa-lib", "futures", + "itertools 0.12.1", "log", "serde", "serde_derive", @@ -1181,6 +1182,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -1998,7 +2008,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" dependencies = [ - "itertools", + "itertools 0.11.0", "nom", "unicode_categories", ] diff --git a/emgauwa-core/Cargo.toml b/emgauwa-core/Cargo.toml index 1bb4ef4..a3dd89a 100644 --- a/emgauwa-core/Cargo.toml +++ b/emgauwa-core/Cargo.toml @@ -19,6 +19,7 @@ log = "0.4" chrono = { version = "0.4", features = ["serde"] } uuid = { version = "1.5", features = ["serde", "v4"] } +itertools = "0.12" serde = "1.0" serde_json = "1.0" diff --git a/emgauwa-core/src/handlers/v1/schedules.rs b/emgauwa-core/src/handlers/v1/schedules.rs index 1130e6b..21bef5a 100644 --- a/emgauwa-core/src/handlers/v1/schedules.rs +++ b/emgauwa-core/src/handlers/v1/schedules.rs @@ -1,11 +1,18 @@ +use actix::Addr; use actix_web::{delete, get, post, put, web, HttpResponse}; -use emgauwa_lib::db::{DbSchedule, DbTag}; +use emgauwa_lib::db::{DbController, DbJunctionRelaySchedule, DbSchedule, DbTag}; use emgauwa_lib::errors::{ApiError, DatabaseError, EmgauwaError}; use emgauwa_lib::models::{convert_db_list, FromDbModel, Schedule}; -use emgauwa_lib::types::{RequestCreateSchedule, RequestUpdateSchedule, ScheduleUid}; +use emgauwa_lib::types::{ + ControllerWsAction, RequestCreateSchedule, RequestUpdateSchedule, ScheduleUid, +}; +use itertools::Itertools; use sqlx::pool::PoolConnection; use sqlx::{Pool, Sqlite}; +use crate::app_state; +use crate::app_state::AppState; + #[get("/schedules")] pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { let mut pool_conn = pool.acquire().await?; @@ -116,6 +123,7 @@ pub async fn add_list( #[put("/schedules/{schedule_id}")] pub async fn update( pool: web::Data<Pool<Sqlite>>, + app_state: web::Data<Addr<AppState>>, path: web::Path<(String,)>, data: web::Json<RequestUpdateSchedule>, ) -> Result<HttpResponse, EmgauwaError> { @@ -144,6 +152,26 @@ pub async fn update( schedule.set_tags(&mut pool_conn, tags.as_slice()).await?; } + let controller_ids: Vec<i64> = DbJunctionRelaySchedule::get_relays(&mut pool_conn, &schedule) + .await? + .into_iter() + .map(|r| r.controller_id) + .unique() + .collect(); + + for controller_id in controller_ids { + let controller = DbController::get(&mut pool_conn, controller_id) + .await? + .ok_or(DatabaseError::NotFound)?; + app_state + .send(app_state::Action { + controller_uid: controller.uid, + action: ControllerWsAction::Schedules(vec![schedule.clone()]), + }) + .await??; + } + + let return_schedule = Schedule::from_db_model(&mut pool_conn, schedule)?; Ok(HttpResponse::Ok().json(return_schedule)) } diff --git a/emgauwa-lib/src/db/junction_relay_schedule.rs b/emgauwa-lib/src/db/junction_relay_schedule.rs index 128490b..f081a54 100644 --- a/emgauwa-lib/src/db/junction_relay_schedule.rs +++ b/emgauwa-lib/src/db/junction_relay_schedule.rs @@ -45,6 +45,23 @@ impl DbJunctionRelaySchedule { .map_err(DatabaseError::from) } + pub async fn get_relays( + conn: &mut PoolConnection<Sqlite>, + schedule: &DbSchedule, + ) -> Result<Vec<DbRelay>, DatabaseError> { + sqlx::query_as!( + DbRelay, + r#"SELECT relays.* FROM relays INNER JOIN junction_relay_schedule + ON junction_relay_schedule.relay_id = relays.id + WHERE junction_relay_schedule.schedule_id = ? + ORDER BY junction_relay_schedule.weekday"#, + schedule.id + ) + .fetch_all(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + pub async fn get_schedule( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay,