Add junction between relays and schedules
This commit is contained in:
		
							parent
							
								
									a90ea25b87
								
							
						
					
					
						commit
						2f51ebf91e
					
				
					 10 changed files with 209 additions and 53 deletions
				
			
		
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,10 +2,12 @@
 | 
			
		|||
build:
 | 
			
		||||
	cargo build
 | 
			
		||||
 | 
			
		||||
sqlx:
 | 
			
		||||
sqlx-prepare:
 | 
			
		||||
	rm ./emgauwa-dev.sqlite || true
 | 
			
		||||
	cargo sqlx database create
 | 
			
		||||
	cargo sqlx migrate run
 | 
			
		||||
 | 
			
		||||
sqlx: sqlx-prepare
 | 
			
		||||
	cargo sqlx prepare --workspace
 | 
			
		||||
 | 
			
		||||
build-rpi:
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +17,7 @@ clean-db:
 | 
			
		|||
	rm ./emgauwa-dev.sqlite || true
 | 
			
		||||
	rm ./emgauwa-core.sqlite || true
 | 
			
		||||
	rm ./emgauwa-controller.sqlite || true
 | 
			
		||||
	$(MAKE) sqlx
 | 
			
		||||
	$(MAKE) sqlx-prepare
 | 
			
		||||
 | 
			
		||||
fmt:
 | 
			
		||||
	cargo +nightly fmt
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
use emgauwa_lib::constants::WEBSOCKET_RETRY_TIMEOUT;
 | 
			
		||||
use emgauwa_lib::db::{DbController, DbRelay};
 | 
			
		||||
use emgauwa_lib::db::errors::DatabaseError;
 | 
			
		||||
use emgauwa_lib::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule};
 | 
			
		||||
use emgauwa_lib::models::{Controller, FromDbModel};
 | 
			
		||||
use emgauwa_lib::types::{ControllerUid, ControllerWsAction};
 | 
			
		||||
use emgauwa_lib::{db, utils};
 | 
			
		||||
| 
						 | 
				
			
			@ -37,15 +38,21 @@ async fn create_this_relay(
 | 
			
		|||
	conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
	this_controller: &DbController,
 | 
			
		||||
	settings_relay: &settings::Relay,
 | 
			
		||||
) -> DbRelay {
 | 
			
		||||
	DbRelay::create(
 | 
			
		||||
) -> Result<DbRelay, DatabaseError> {
 | 
			
		||||
	let relay = DbRelay::create(
 | 
			
		||||
		conn,
 | 
			
		||||
		&settings_relay.name,
 | 
			
		||||
		settings_relay.number.unwrap(),
 | 
			
		||||
		this_controller,
 | 
			
		||||
	)
 | 
			
		||||
	.await
 | 
			
		||||
	.expect("Failed to create relay")
 | 
			
		||||
	.await?;
 | 
			
		||||
 | 
			
		||||
	let off = DbSchedule::get_off(conn).await?;
 | 
			
		||||
	for weekday in 0..7 {
 | 
			
		||||
		DbJunctionRelaySchedule::set_schedule(conn, &relay, &off, weekday).await?;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Ok(relay)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::main]
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +78,9 @@ async fn main() {
 | 
			
		|||
			.expect("Failed to get relay from database")
 | 
			
		||||
			.is_none()
 | 
			
		||||
		{
 | 
			
		||||
			create_this_relay(&mut conn, &db_controller, relay).await;
 | 
			
		||||
			create_this_relay(&mut conn, &db_controller, relay)
 | 
			
		||||
				.await
 | 
			
		||||
				.expect("Failed to create schedule.");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										131
									
								
								emgauwa-lib/src/db/junction_relay_schedule.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								emgauwa-lib/src/db/junction_relay_schedule.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,131 @@
 | 
			
		|||
use std::ops::DerefMut;
 | 
			
		||||
 | 
			
		||||
use sqlx::pool::PoolConnection;
 | 
			
		||||
use sqlx::Sqlite;
 | 
			
		||||
 | 
			
		||||
use crate::db::errors::DatabaseError;
 | 
			
		||||
use crate::db::{DbRelay, DbSchedule};
 | 
			
		||||
use crate::types::Weekday;
 | 
			
		||||
 | 
			
		||||
pub struct DbJunctionRelaySchedule {
 | 
			
		||||
	pub id: i64,
 | 
			
		||||
	pub weekday: Weekday,
 | 
			
		||||
	pub relay_id: i64,
 | 
			
		||||
	pub schedule_id: i64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DbJunctionRelaySchedule {
 | 
			
		||||
	pub async fn get(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		id: i64,
 | 
			
		||||
	) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionRelaySchedule,
 | 
			
		||||
			"SELECT * FROM junction_relay_schedule WHERE id = ?",
 | 
			
		||||
			id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await
 | 
			
		||||
		.map_err(DatabaseError::from)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn get_junction(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
		schedule: &DbSchedule,
 | 
			
		||||
		weekday: Weekday,
 | 
			
		||||
	) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionRelaySchedule,
 | 
			
		||||
			"SELECT * FROM junction_relay_schedule WHERE relay_id = ? AND schedule_id = ? AND weekday = ?",
 | 
			
		||||
			relay.id,
 | 
			
		||||
            schedule.id,
 | 
			
		||||
			weekday
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await
 | 
			
		||||
		.map_err(DatabaseError::from)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn get_schedule(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
		weekday: Weekday,
 | 
			
		||||
	) -> Result<Option<DbSchedule>, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbSchedule,
 | 
			
		||||
			r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule
 | 
			
		||||
			ON junction_relay_schedule.schedule_id = schedules.id
 | 
			
		||||
			WHERE junction_relay_schedule.relay_id = ? AND junction_relay_schedule.weekday = ?"#,
 | 
			
		||||
			relay.id,
 | 
			
		||||
			weekday
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await
 | 
			
		||||
		.map_err(DatabaseError::from)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn get_schedules(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
	) -> Result<Vec<DbSchedule>, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbSchedule,
 | 
			
		||||
			r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule
 | 
			
		||||
			ON junction_relay_schedule.schedule_id = schedules.id
 | 
			
		||||
			WHERE junction_relay_schedule.relay_id = ?
 | 
			
		||||
			ORDER BY junction_relay_schedule.weekday"#,
 | 
			
		||||
			relay.id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_all(conn.deref_mut())
 | 
			
		||||
		.await
 | 
			
		||||
		.map_err(DatabaseError::from)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn set_schedule(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
		schedule: &DbSchedule,
 | 
			
		||||
		weekday: Weekday,
 | 
			
		||||
	) -> Result<DbJunctionRelaySchedule, DatabaseError> {
 | 
			
		||||
		match Self::get_junction(conn, relay, schedule, weekday).await? {
 | 
			
		||||
			None => sqlx::query_as!(
 | 
			
		||||
				DbJunctionRelaySchedule,
 | 
			
		||||
				"INSERT INTO junction_relay_schedule (weekday, relay_id, schedule_id) VALUES (?, ?, ?) RETURNING *",
 | 
			
		||||
				weekday,
 | 
			
		||||
				relay.id,
 | 
			
		||||
				schedule.id
 | 
			
		||||
			)
 | 
			
		||||
			.fetch_optional(conn.deref_mut())
 | 
			
		||||
			.await?
 | 
			
		||||
			.ok_or(DatabaseError::InsertGetError),
 | 
			
		||||
 | 
			
		||||
			Some(junction) => {
 | 
			
		||||
				sqlx::query!(
 | 
			
		||||
                    "UPDATE junction_relay_schedule SET weekday = ?, relay_id = ?, schedule_id= ? WHERE id = ?",
 | 
			
		||||
                    weekday,
 | 
			
		||||
                    relay.id,
 | 
			
		||||
                    schedule.id,
 | 
			
		||||
					junction.id
 | 
			
		||||
                )
 | 
			
		||||
					.execute(conn.deref_mut())
 | 
			
		||||
					.await?;
 | 
			
		||||
 | 
			
		||||
				Self::get(conn, junction.id)
 | 
			
		||||
					.await?
 | 
			
		||||
					.ok_or(DatabaseError::UpdateGetError)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn set_schedules(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
		schedules: Vec<&DbSchedule>,
 | 
			
		||||
	) -> Result<(), DatabaseError> {
 | 
			
		||||
		for (weekday, schedule) in schedules.iter().enumerate() {
 | 
			
		||||
			Self::set_schedule(conn, relay, schedule, weekday as Weekday).await?;
 | 
			
		||||
		}
 | 
			
		||||
		Ok(())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								emgauwa-lib/src/db/junction_tag.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								emgauwa-lib/src/db/junction_tag.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
use std::ops::DerefMut;
 | 
			
		||||
 | 
			
		||||
use sqlx::pool::PoolConnection;
 | 
			
		||||
use sqlx::Sqlite;
 | 
			
		||||
 | 
			
		||||
use crate::db::errors::DatabaseError;
 | 
			
		||||
use crate::db::{DbRelay, DbSchedule, DbTag};
 | 
			
		||||
 | 
			
		||||
pub struct DbJunctionTag {
 | 
			
		||||
	pub id: i64,
 | 
			
		||||
	pub tag_id: i64,
 | 
			
		||||
	pub relay_id: Option<i64>,
 | 
			
		||||
	pub schedule_id: Option<i64>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DbJunctionTag {
 | 
			
		||||
	pub async fn link_relay(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		tag: &DbTag,
 | 
			
		||||
		relay: &DbRelay,
 | 
			
		||||
	) -> Result<DbJunctionTag, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionTag,
 | 
			
		||||
			"INSERT INTO junction_tag (tag_id, relay_id) VALUES (?, ?) RETURNING *",
 | 
			
		||||
			tag.id,
 | 
			
		||||
			relay.id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await?
 | 
			
		||||
		.ok_or(DatabaseError::InsertGetError)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn link_schedule(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		tag: &DbTag,
 | 
			
		||||
		schedule: &DbSchedule,
 | 
			
		||||
	) -> Result<DbJunctionTag, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionTag,
 | 
			
		||||
			"INSERT INTO junction_tag (tag_id, schedule_id) VALUES (?, ?) RETURNING *",
 | 
			
		||||
			tag.id,
 | 
			
		||||
			schedule.id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await?
 | 
			
		||||
		.ok_or(DatabaseError::InsertGetError)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,12 +6,16 @@ use sqlx::{Pool, Sqlite};
 | 
			
		|||
 | 
			
		||||
mod controllers;
 | 
			
		||||
pub mod errors;
 | 
			
		||||
mod junction_relay_schedule;
 | 
			
		||||
mod junction_tag;
 | 
			
		||||
mod model_utils;
 | 
			
		||||
mod relays;
 | 
			
		||||
mod schedules;
 | 
			
		||||
mod tag;
 | 
			
		||||
 | 
			
		||||
pub use controllers::DbController;
 | 
			
		||||
pub use junction_relay_schedule::DbJunctionRelaySchedule;
 | 
			
		||||
pub use junction_tag::DbJunctionTag;
 | 
			
		||||
pub use relays::DbRelay;
 | 
			
		||||
pub use schedules::{DbPeriods, DbSchedule};
 | 
			
		||||
pub use tag::DbTag;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ use sqlx::pool::PoolConnection;
 | 
			
		|||
use sqlx::Sqlite;
 | 
			
		||||
 | 
			
		||||
use crate::db::errors::DatabaseError;
 | 
			
		||||
use crate::db::{DbController, DbTag};
 | 
			
		||||
use crate::db::{DbController, DbJunctionTag, DbTag};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
pub struct DbRelay {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ impl DbRelay {
 | 
			
		|||
 | 
			
		||||
		for new_tag in new_tags {
 | 
			
		||||
			let tag: DbTag = DbTag::get_by_tag_or_create(conn, new_tag).await?;
 | 
			
		||||
			tag.link_relay(conn, self).await?;
 | 
			
		||||
			DbJunctionTag::link_relay(conn, &tag, self).await?;
 | 
			
		||||
		}
 | 
			
		||||
		Ok(())
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ use sqlx::Sqlite;
 | 
			
		|||
 | 
			
		||||
use crate::db::errors::DatabaseError;
 | 
			
		||||
use crate::db::model_utils::Period;
 | 
			
		||||
use crate::db::DbTag;
 | 
			
		||||
use crate::db::{DbJunctionTag, DbTag};
 | 
			
		||||
use crate::types::ScheduleUid;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ impl DbSchedule {
 | 
			
		|||
 | 
			
		||||
		for new_tag in new_tags {
 | 
			
		||||
			let tag: DbTag = DbTag::get_by_tag_or_create(conn, new_tag).await?;
 | 
			
		||||
			tag.link_schedule(conn, self).await?;
 | 
			
		||||
			DbJunctionTag::link_schedule(conn, &tag, self).await?;
 | 
			
		||||
		}
 | 
			
		||||
		Ok(())
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@ use sqlx::pool::PoolConnection;
 | 
			
		|||
use sqlx::Sqlite;
 | 
			
		||||
 | 
			
		||||
use crate::db::errors::DatabaseError;
 | 
			
		||||
use crate::db::{DbRelay, DbSchedule};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Serialize, Clone)]
 | 
			
		||||
pub struct DbTag {
 | 
			
		||||
| 
						 | 
				
			
			@ -13,13 +12,6 @@ pub struct DbTag {
 | 
			
		|||
	pub tag: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct DbJunctionTag {
 | 
			
		||||
	pub id: i64,
 | 
			
		||||
	pub tag_id: i64,
 | 
			
		||||
	pub relay_id: Option<i64>,
 | 
			
		||||
	pub schedule_id: Option<i64>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DbTag {
 | 
			
		||||
	pub async fn create(
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
| 
						 | 
				
			
			@ -64,36 +56,4 @@ impl DbTag {
 | 
			
		|||
			.await
 | 
			
		||||
			.map_err(DatabaseError::from)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn link_relay(
 | 
			
		||||
		&self,
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		target_relay: &DbRelay,
 | 
			
		||||
	) -> Result<DbJunctionTag, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionTag,
 | 
			
		||||
			"INSERT INTO junction_tag (tag_id, relay_id) VALUES (?, ?) RETURNING *",
 | 
			
		||||
			self.id,
 | 
			
		||||
			target_relay.id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await?
 | 
			
		||||
		.ok_or(DatabaseError::InsertGetError)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub async fn link_schedule(
 | 
			
		||||
		&self,
 | 
			
		||||
		conn: &mut PoolConnection<Sqlite>,
 | 
			
		||||
		target_schedule: &DbSchedule,
 | 
			
		||||
	) -> Result<DbJunctionTag, DatabaseError> {
 | 
			
		||||
		sqlx::query_as!(
 | 
			
		||||
			DbJunctionTag,
 | 
			
		||||
			"INSERT INTO junction_tag (tag_id, schedule_id) VALUES (?, ?) RETURNING *",
 | 
			
		||||
			self.id,
 | 
			
		||||
			target_schedule.id
 | 
			
		||||
		)
 | 
			
		||||
		.fetch_optional(conn.deref_mut())
 | 
			
		||||
		.await?
 | 
			
		||||
		.ok_or(DatabaseError::InsertGetError)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ use serde_derive::{Deserialize, Serialize};
 | 
			
		|||
use crate::models::Controller;
 | 
			
		||||
 | 
			
		||||
pub type ConnectedControllersType = Arc<Mutex<HashMap<ControllerUid, Controller>>>;
 | 
			
		||||
pub type Weekday = i64;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Serialize, Deserialize)]
 | 
			
		||||
pub enum ControllerWsAction {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,11 +107,12 @@ CREATE TABLE junction_relay_schedule
 | 
			
		|||
        NOT NULL,
 | 
			
		||||
    relay_id
 | 
			
		||||
        INTEGER
 | 
			
		||||
        NOT NULL
 | 
			
		||||
        REFERENCES relays (id)
 | 
			
		||||
            ON DELETE CASCADE,
 | 
			
		||||
    schedule_id
 | 
			
		||||
        INTEGER
 | 
			
		||||
        DEFAULT 1
 | 
			
		||||
        NOT NULL
 | 
			
		||||
        REFERENCES schedules (id)
 | 
			
		||||
            ON DELETE SET DEFAULT
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue