From d76bf0f711dc5e620ddc489ae762cb88a3d8e349 Mon Sep 17 00:00:00 2001
From: Tobias Reisinger <tobias@msrg.cc>
Date: Mon, 13 May 2024 19:17:24 +0200
Subject: [PATCH] Improve macro-execute function and simplify schedule in macro
 action

---
 api.v1.json               | 10 +++---
 src/handlers/v1/macros.rs | 74 ++++++++++++++++++++++++++-------------
 2 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/api.v1.json b/api.v1.json
index e6988fa..6e5218c 100644
--- a/api.v1.json
+++ b/api.v1.json
@@ -1116,14 +1116,14 @@
             "$ref": "#/components/schemas/controller_id"
           },
           "active_schedule": {
-            "$ref": "#/components/schemas/schedule-untagged"
+            "$ref": "#/components/schemas/schedule_simple"
           },
           "schedules": {
             "type": "array",
             "maxItems": 7,
             "minItems": 7,
             "items": {
-              "$ref": "#/components/schemas/schedule-untagged"
+              "$ref": "#/components/schemas/schedule_simple"
             }
           },
           "tags": {
@@ -1139,8 +1139,8 @@
           }
         }
       },
-      "schedule-untagged": {
-        "title": "schedule",
+      "schedule_simple": {
+        "title": "schedule (simple)",
         "type": "object",
         "description": "",
         "properties": {
@@ -1274,7 +1274,7 @@
             "maximum": 6
           },
           "schedule": {
-            "$ref": "#/components/schemas/schedule"
+            "$ref": "#/components/schemas/schedule_simple"
           },
           "relay": {
             "$ref": "#/components/schemas/relay"
diff --git a/src/handlers/v1/macros.rs b/src/handlers/v1/macros.rs
index d76bfef..44b9957 100644
--- a/src/handlers/v1/macros.rs
+++ b/src/handlers/v1/macros.rs
@@ -1,16 +1,14 @@
 use actix::Addr;
 use actix_web::{delete, get, HttpResponse, post, put, web};
-use itertools::Itertools;
 use sqlx::{Pool, Sqlite};
+use sqlx::pool::PoolConnection;
 
-use emgauwa_common::db::DbMacro;
+use emgauwa_common::db::{DbController, DbMacro};
 use emgauwa_common::errors::{DatabaseError, EmgauwaError};
 use emgauwa_common::models::{convert_db_list, FromDbModel, Macro, MacroAction, Relay};
-use emgauwa_common::types::{
-	ControllerWsAction, EmgauwaUid, RequestMacroCreate, RequestMacroExecute, RequestMacroUpdate,
-};
-
+use emgauwa_common::types::{ControllerWsAction, EmgauwaUid, RequestMacroCreate, RequestMacroExecute, RequestMacroUpdate};
 use crate::app_state;
+
 use crate::app_state::AppState;
 use crate::handlers::EmgauwaMessage;
 
@@ -132,30 +130,15 @@ pub async fn execute(
 		action.execute(&mut pool_conn).await?;
 	}
 
-	let affected_controller_uids: Vec<EmgauwaUid> = actions
-		.iter()
-		.map(|action| action.relay.controller_id.clone())
-		.unique()
-		.collect();
+	let affected_controllers = collect_affected_controllers(&mut pool_conn, &actions).await?;
 
-	for controller_uid in affected_controller_uids {
-		let mut affected_relays: Vec<Relay> = Vec::new();
-		let mut affected_relay_ids: Vec<i64> = Vec::new();
+	for controller in affected_controllers {
 
-		for action in actions.iter_mut() {
-			if affected_relay_ids.contains(&action.relay.r.id)
-				|| action.relay.controller_id != controller_uid
-			{
-				continue;
-			}
-			action.relay.reload(&mut pool_conn)?;
-			affected_relays.push(action.relay.clone());
-			affected_relay_ids.push(action.relay.r.id);
-		}
+		let affected_relays = collect_affected_relays(&mut pool_conn, &mut actions, &controller).await?;
 
 		app_state
 			.send(app_state::Action {
-				controller_uid,
+				controller_uid: controller.uid,
 				action: ControllerWsAction::Relays(affected_relays.clone()),
 			})
 			.await??;
@@ -163,3 +146,44 @@ pub async fn execute(
 
 	Ok(HttpResponse::Ok().emgauwa_message("macro got executed"))
 }
+
+async fn collect_affected_controllers(
+	pool_conn: &mut PoolConnection<Sqlite>,
+	actions: &Vec<MacroAction>,
+) -> Result<Vec<DbController>, DatabaseError> {
+	let mut affected_controllers: Vec<DbController> = Vec::new();
+	for action in actions {
+		let controller_id = action.relay.r.controller_id;
+
+		if affected_controllers
+			.iter()
+			.any(|controller| controller.id == controller_id)
+		{
+			continue
+		}
+
+		let controller = DbController::get(pool_conn, controller_id).await?
+			.ok_or(DatabaseError::NotFound)?;
+		affected_controllers.push(controller);
+	}
+	Ok(affected_controllers)
+}
+
+async fn collect_affected_relays(
+	pool_conn: &mut PoolConnection<Sqlite>,
+	actions: &mut Vec<MacroAction>,
+	controller: &DbController,
+) -> Result<Vec<Relay>, DatabaseError> {
+	let mut affected_relays: Vec<Relay> = Vec::new();
+
+	for action in actions {
+		if affected_relays.iter().any(|relay| relay.r.id == action.relay.r.id)
+			|| action.relay.r.controller_id != controller.id
+		{
+			continue;
+		}
+		action.relay.reload(pool_conn)?;
+		affected_relays.push(action.relay.clone());
+	}
+	Ok(affected_relays)
+}
\ No newline at end of file