From 73137b82ce1d274acb825c76c8e4f99c62826cb4 Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Tue, 24 Jan 2023 20:19:38 +0100 Subject: [PATCH] RUST: Separate connexion and queue + add todo functions + update visibilities --- .../liblektor-rs/lektor_db/src/connexion.rs | 64 +++---------- src/rust/liblektor-rs/lektor_db/src/lib.rs | 7 +- src/rust/liblektor-rs/lektor_db/src/models.rs | 24 +++-- src/rust/liblektor-rs/lektor_db/src/queue.rs | 93 ++++++++++++++----- 4 files changed, 103 insertions(+), 85 deletions(-) diff --git a/src/rust/liblektor-rs/lektor_db/src/connexion.rs b/src/rust/liblektor-rs/lektor_db/src/connexion.rs index eb4da471..ee7ec977 100644 --- a/src/rust/liblektor-rs/lektor_db/src/connexion.rs +++ b/src/rust/liblektor-rs/lektor_db/src/connexion.rs @@ -1,8 +1,4 @@ -use crate::{ - models::*, - queue::{LktDatabasePriority, LktDatabaseQueueRangeIter}, - *, -}; +use crate::{models::*, *}; use kurisu_api::v1 as api_v1; use lektor_c_compat::rs::LktCUri; @@ -19,7 +15,6 @@ fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, Strin pub struct LktDatabaseConnection { sqlite: SqliteConnection, - queue: queue::LktDatabaseQueue, } /// Get the value of a [LktCUri] and returns Err(String) in case of invalid @@ -86,10 +81,7 @@ impl LktDatabaseConnection { })?; let sqlite = establish_connection(path.to_string_lossy()).map_err(LktDatabaseError::String)?; - Ok(Self { - sqlite, - queue: Default::default(), - }) + Ok(Self { sqlite }) } /// Get a tag id by its name. If the tag doesn't exists, create it. @@ -152,10 +144,7 @@ impl LktDatabaseConnection { /// Ensure that a given language is present in the database. If it's not /// insert it. Existence test is done on the code of the language. - pub fn ensure_languages_exist<'a>( - &mut self, - langs: &[NewLanguage<'a>], - ) -> LktDatabaseResult<()> { + fn ensure_languages_exist<'a>(&mut self, langs: &[NewLanguage<'a>]) -> LktDatabaseResult<()> { self.sqlite.exclusive_transaction(|c| { for lang in langs { with_dsl!(iso_639_1 => match iso_639_1.filter(code.eq(lang.code)).count().get_result(c)? { @@ -168,6 +157,18 @@ impl LktDatabaseConnection { }) } + /// Add a kara to the history. + pub fn add_to_history(&mut self, kara: i64) -> LktDatabaseResult<()> { + self.sqlite.exclusive_transaction(|conn| { + with_dsl!(history => { + let epok = history.select(max(epoch)).first::<Option<i64>>(conn)?.unwrap_or_default() + 1; + diesel::delete(history.filter(id.is(kara))).execute(conn)?; + diesel::insert_into(history).values(HistoryRecord { kara_id: kara, epoch: epok }).execute(conn)?; + Ok(()) + }) + }) + } + /// Add a kara with a request. pub fn add_kara_from_request(&mut self, kara: NewKaraRequest) -> LktDatabaseResult<()> { let (id, new_kara, karamakers, langs, tags) = kara; @@ -222,41 +223,6 @@ impl LktDatabaseConnection { Ok((id, kara, kara_maker, vec![lang], tags)) } - /// Peek the next kara to play - pub fn peek_next_kara_in_queue(&self) -> Option<i64> { - self.queue.peek_next().copied() - } - - /// Pop the next kara to play - pub fn pop_next_kara_in_queue(&mut self) -> Option<i64> { - self.queue.pop_next() - } - - /// Get the content of the queue from a range. - pub fn get_queue_content(&self, range: Range<usize>) -> LktDatabaseQueueRangeIter { - self.queue.range(range) - } - - /// Add a kara at the end of the queue. - pub fn enqueue_kara(&mut self, local_id: i64) { - self.queue.enqueue_kara(local_id) - } - - /// Add a kara at the end of a priority in the queue. - pub fn enqueue_kara_with_priority(&mut self, local_id: i64, priority: LktDatabasePriority) { - self.queue.enqueue_kara_with_priority(local_id, priority) - } - - /// Add a kara at the top of the queue. - pub fn insert_kara(&mut self, local_id: i64) { - self.queue.insert_kara(local_id) - } - - /// Add a kara at the top of a priority in the queue. - pub fn insert_kara_with_priority(&mut self, local_id: i64, priority: LktDatabasePriority) { - self.queue.insert_kara_with_priority(local_id, priority) - } - /// Search the queue by URIs. We return the local ids. pub fn queue_search(&mut self, _uri: LktCUri) -> Result<Vec<i64>, String> { todo!() diff --git a/src/rust/liblektor-rs/lektor_db/src/lib.rs b/src/rust/liblektor-rs/lektor_db/src/lib.rs index b29f7c4f..9767296a 100644 --- a/src/rust/liblektor-rs/lektor_db/src/lib.rs +++ b/src/rust/liblektor-rs/lektor_db/src/lib.rs @@ -4,16 +4,17 @@ pub mod connexion; pub mod error; -pub mod models; pub mod queue; -pub mod schema; + +pub(self) mod models; +pub(self) mod schema; pub(self) use diesel::prelude::*; pub(self) use error::*; pub(self) use std::{collections::VecDeque, ops::Range, path::Path}; /// All the information needed to add a kara recieved from a repo! -pub type NewKaraRequest<'a> = ( +pub(self) type NewKaraRequest<'a> = ( models::KaraId, models::NewKara<'a>, Vec<models::NewKaraMaker<'a>>, diff --git a/src/rust/liblektor-rs/lektor_db/src/models.rs b/src/rust/liblektor-rs/lektor_db/src/models.rs index fb58d92f..c4b53052 100644 --- a/src/rust/liblektor-rs/lektor_db/src/models.rs +++ b/src/rust/liblektor-rs/lektor_db/src/models.rs @@ -4,6 +4,22 @@ use crate::{schema::*, *}; use diesel::{deserialize::FromSqlRow, expression::AsExpression, sql_types}; use kurisu_api::v1 as api_v1; +#[derive(Debug, Insertable, Queryable, Selectable)] +#[diesel(table_name = repo_kara)] +pub struct KaraId { + pub repo_id: i64, + pub repo_kara_id: i64, + pub local_kara_id: i64, +} + +#[derive(Debug, Insertable, Queryable, Selectable)] +#[diesel(table_name = history)] +pub struct HistoryRecord { + #[diesel(column_name = "id")] + pub kara_id: i64, + pub epoch: i64, +} + // First the insertable things #[derive(Insertable)] @@ -13,14 +29,6 @@ pub struct NewRepo<'a> { pub name: &'a str, } -#[derive(Debug, Insertable, Queryable, Selectable)] -#[diesel(table_name = repo_kara)] -pub struct KaraId { - pub repo_id: i64, - pub repo_kara_id: i64, - pub local_kara_id: i64, -} - #[derive(Debug, Insertable)] #[diesel(table_name = kara)] pub struct NewKara<'a> { diff --git a/src/rust/liblektor-rs/lektor_db/src/queue.rs b/src/rust/liblektor-rs/lektor_db/src/queue.rs index 54e3f143..558dc3bd 100644 --- a/src/rust/liblektor-rs/lektor_db/src/queue.rs +++ b/src/rust/liblektor-rs/lektor_db/src/queue.rs @@ -5,6 +5,7 @@ use super::*; const LKT_DATABASE_QUEUES_COUNT: usize = 5; /// A type to describe a priority. +#[derive(Debug, Default)] pub struct LktDatabasePriority { /// The actual priority. Alaways between `0` and /// [LKT_DATABASE_QUEUES_COUNT], both included. @@ -21,6 +22,11 @@ macro_rules! impl_from_for_proprity { } } }; + + ($ty: ty, $($tys: ty),+) => { + impl_from_for_proprity!($ty); + impl_from_for_proprity!($($tys),+); + } } macro_rules! impl_into_for_priority { @@ -31,19 +37,15 @@ macro_rules! impl_into_for_priority { } } }; -} - -impl_from_for_proprity!(u8); -impl_from_for_proprity!(u16); -impl_from_for_proprity!(u32); -impl_from_for_proprity!(u64); -impl_from_for_proprity!(i8); -impl_from_for_proprity!(i16); -impl_from_for_proprity!(i32); -impl_from_for_proprity!(i64); + ($ty: ty, $($tys: ty),+) => { + impl_into_for_priority!($ty); + impl_into_for_priority!($($tys),+); + } +} -impl_into_for_priority!(usize); +impl_from_for_proprity!(u8, u16, u32, u64, i8, i16, i32, i64); +impl_into_for_priority!(usize, isize); /// The iterator for the database queue. The iterator returns references to /// karas' id to protect modifications while a reference to some karas are @@ -63,12 +65,12 @@ pub struct LktDatabaseQueueRangeIter<'a> { } impl<'a> Iterator for LktDatabaseQueueIter<'a> { - type Item = &'a i64; + type Item = i64; fn next(&mut self) -> Option<Self::Item> { let priority = self.priority?.clamp(0, LKT_DATABASE_QUEUES_COUNT - 1); let level = &self.queue.levels[priority]; - match level.get(self.index) { + match level.get(self.index).copied() { Some(ret) => { self.index += 1; Some(ret) @@ -83,7 +85,7 @@ impl<'a> Iterator for LktDatabaseQueueIter<'a> { } impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> { - type Item = &'a i64; + type Item = i64; fn next(&mut self) -> Option<Self::Item> { let new_remaining = self.remaining.saturating_sub(1); @@ -100,27 +102,32 @@ impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> { #[derive(Debug, Default)] pub struct LktDatabaseQueue { levels: [VecDeque<i64>; LKT_DATABASE_QUEUES_COUNT], + current: Option<i64>, } impl LktDatabaseQueue { - pub fn enqueue_kara(&mut self, local_id: i64) { - self.levels[0].push_back(local_id); + /// Get the current kara in the queue. + pub fn current_kara(&self) -> Option<i64> { + self.current } - pub fn enqueue_kara_with_priority(&mut self, local_id: i64, priority: LktDatabasePriority) { + /// Add a kara in the queue with a given priority. + pub fn add_kara(&mut self, local_id: i64, priority: LktDatabasePriority) { let priority: usize = priority.into(); self.levels[priority].push_back(local_id); } - pub fn insert_kara(&mut self, local_id: i64) { - self.levels[LKT_DATABASE_QUEUES_COUNT - 1].push_front(local_id); - } - - pub fn insert_kara_with_priority(&mut self, local_id: i64, priority: LktDatabasePriority) { + /// Add all karas in the queue with a given priority in the passed order. + pub fn add_kara_all<I: IntoIterator<Item = i64>>( + &mut self, + local_ids: I, + priority: LktDatabasePriority, + ) { let priority: usize = priority.into(); - self.levels[priority].push_front(local_id); + self.levels[priority].extend(local_ids.into_iter()); } + /// Iterate over the queue content. pub fn iter(&self) -> LktDatabaseQueueIter { let priority = self .levels @@ -135,19 +142,25 @@ impl LktDatabaseQueue { } } - pub fn peek_next(&self) -> Option<&i64> { + /// Peek the next kara to play in the queue. + pub fn peek_next(&self) -> Option<i64> { self.iter().next() } + /// Pop the next kara from the queue and set the current kara to the + /// returned value. pub fn pop_next(&mut self) -> Option<i64> { let level = self .levels .iter_mut() .rev() .find(|content| !content.is_empty())?; - level.pop_front() + let current = level.pop_front(); + self.current = current; + current } + /// Get a range of karas in queue. pub fn range(&self, range: Range<usize>) -> LktDatabaseQueueRangeIter { let mut iter = self.iter(); let remaining = range.end.saturating_sub(range.start); @@ -161,4 +174,34 @@ impl LktDatabaseQueue { remaining, } } + + /// Swap two karas with their positions. Returns the two karas that were + /// swaped, the order is not defined. On error returns what went wrong. + pub fn swap(&mut self, _from: usize, _to: usize) -> Result<(i64, i64), String> { + todo!() + } + + /// Delete all occurencies of a given kara in the queue. Returns the number + /// of deleted entries. + pub fn delete_all(&mut self, _kara_id: i64) -> usize { + todo!() + } + + /// Clear the queue, returns the number of delete entries. This also clears + /// the current kara if the maximal level is passed. Only clears up to + /// (including) the passed level. + pub fn clear(&mut self, _up_to: LktDatabasePriority) -> usize { + todo!() + } + + /// Crop the queue. Only the current kara remains. Returns the number of + /// deleted entries. + pub fn crop(&mut self) -> usize { + todo!() + } + + /// Shuffle the queue. Do the shuffle in a per-level way. + pub fn shuffle(&mut self) { + todo!() + } } -- GitLab