Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 73137b82 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

RUST: Separate connexion and queue + add todo functions + update visibilities

parent fc5596bf
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
use crate::{ use crate::{models::*, *};
models::*,
queue::{LktDatabasePriority, LktDatabaseQueueRangeIter},
*,
};
use kurisu_api::v1 as api_v1; use kurisu_api::v1 as api_v1;
use lektor_c_compat::rs::LktCUri; use lektor_c_compat::rs::LktCUri;
...@@ -19,7 +15,6 @@ fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, Strin ...@@ -19,7 +15,6 @@ fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, Strin
pub struct LktDatabaseConnection { pub struct LktDatabaseConnection {
sqlite: SqliteConnection, sqlite: SqliteConnection,
queue: queue::LktDatabaseQueue,
} }
/// Get the value of a [LktCUri] and returns Err(String) in case of invalid /// Get the value of a [LktCUri] and returns Err(String) in case of invalid
...@@ -86,10 +81,7 @@ impl LktDatabaseConnection { ...@@ -86,10 +81,7 @@ impl LktDatabaseConnection {
})?; })?;
let sqlite = let sqlite =
establish_connection(path.to_string_lossy()).map_err(LktDatabaseError::String)?; establish_connection(path.to_string_lossy()).map_err(LktDatabaseError::String)?;
Ok(Self { Ok(Self { sqlite })
sqlite,
queue: Default::default(),
})
} }
/// Get a tag id by its name. If the tag doesn't exists, create it. /// Get a tag id by its name. If the tag doesn't exists, create it.
...@@ -152,10 +144,7 @@ impl LktDatabaseConnection { ...@@ -152,10 +144,7 @@ impl LktDatabaseConnection {
/// Ensure that a given language is present in the database. If it's not /// 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. /// insert it. Existence test is done on the code of the language.
pub fn ensure_languages_exist<'a>( fn ensure_languages_exist<'a>(&mut self, langs: &[NewLanguage<'a>]) -> LktDatabaseResult<()> {
&mut self,
langs: &[NewLanguage<'a>],
) -> LktDatabaseResult<()> {
self.sqlite.exclusive_transaction(|c| { self.sqlite.exclusive_transaction(|c| {
for lang in langs { for lang in langs {
with_dsl!(iso_639_1 => match iso_639_1.filter(code.eq(lang.code)).count().get_result(c)? { with_dsl!(iso_639_1 => match iso_639_1.filter(code.eq(lang.code)).count().get_result(c)? {
...@@ -168,6 +157,18 @@ impl LktDatabaseConnection { ...@@ -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. /// Add a kara with a request.
pub fn add_kara_from_request(&mut self, kara: NewKaraRequest) -> LktDatabaseResult<()> { pub fn add_kara_from_request(&mut self, kara: NewKaraRequest) -> LktDatabaseResult<()> {
let (id, new_kara, karamakers, langs, tags) = kara; let (id, new_kara, karamakers, langs, tags) = kara;
...@@ -222,41 +223,6 @@ impl LktDatabaseConnection { ...@@ -222,41 +223,6 @@ impl LktDatabaseConnection {
Ok((id, kara, kara_maker, vec![lang], tags)) 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. /// Search the queue by URIs. We return the local ids.
pub fn queue_search(&mut self, _uri: LktCUri) -> Result<Vec<i64>, String> { pub fn queue_search(&mut self, _uri: LktCUri) -> Result<Vec<i64>, String> {
todo!() todo!()
......
...@@ -4,16 +4,17 @@ ...@@ -4,16 +4,17 @@
pub mod connexion; pub mod connexion;
pub mod error; pub mod error;
pub mod models;
pub mod queue; pub mod queue;
pub mod schema;
pub(self) mod models;
pub(self) mod schema;
pub(self) use diesel::prelude::*; pub(self) use diesel::prelude::*;
pub(self) use error::*; pub(self) use error::*;
pub(self) use std::{collections::VecDeque, ops::Range, path::Path}; pub(self) use std::{collections::VecDeque, ops::Range, path::Path};
/// All the information needed to add a kara recieved from a repo! /// All the information needed to add a kara recieved from a repo!
pub type NewKaraRequest<'a> = ( pub(self) type NewKaraRequest<'a> = (
models::KaraId, models::KaraId,
models::NewKara<'a>, models::NewKara<'a>,
Vec<models::NewKaraMaker<'a>>, Vec<models::NewKaraMaker<'a>>,
......
...@@ -4,6 +4,22 @@ use crate::{schema::*, *}; ...@@ -4,6 +4,22 @@ use crate::{schema::*, *};
use diesel::{deserialize::FromSqlRow, expression::AsExpression, sql_types}; use diesel::{deserialize::FromSqlRow, expression::AsExpression, sql_types};
use kurisu_api::v1 as api_v1; 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 // First the insertable things
#[derive(Insertable)] #[derive(Insertable)]
...@@ -13,14 +29,6 @@ pub struct NewRepo<'a> { ...@@ -13,14 +29,6 @@ pub struct NewRepo<'a> {
pub name: &'a str, 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)] #[derive(Debug, Insertable)]
#[diesel(table_name = kara)] #[diesel(table_name = kara)]
pub struct NewKara<'a> { pub struct NewKara<'a> {
......
...@@ -5,6 +5,7 @@ use super::*; ...@@ -5,6 +5,7 @@ use super::*;
const LKT_DATABASE_QUEUES_COUNT: usize = 5; const LKT_DATABASE_QUEUES_COUNT: usize = 5;
/// A type to describe a priority. /// A type to describe a priority.
#[derive(Debug, Default)]
pub struct LktDatabasePriority { pub struct LktDatabasePriority {
/// The actual priority. Alaways between `0` and /// The actual priority. Alaways between `0` and
/// [LKT_DATABASE_QUEUES_COUNT], both included. /// [LKT_DATABASE_QUEUES_COUNT], both included.
...@@ -21,6 +22,11 @@ macro_rules! impl_from_for_proprity { ...@@ -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 { macro_rules! impl_into_for_priority {
...@@ -31,19 +37,15 @@ 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); ($ty: ty, $($tys: ty),+) => {
impl_from_for_proprity!(i16); impl_into_for_priority!($ty);
impl_from_for_proprity!(i32); impl_into_for_priority!($($tys),+);
impl_from_for_proprity!(i64); }
}
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 /// The iterator for the database queue. The iterator returns references to
/// karas' id to protect modifications while a reference to some karas are /// karas' id to protect modifications while a reference to some karas are
...@@ -63,12 +65,12 @@ pub struct LktDatabaseQueueRangeIter<'a> { ...@@ -63,12 +65,12 @@ pub struct LktDatabaseQueueRangeIter<'a> {
} }
impl<'a> Iterator for LktDatabaseQueueIter<'a> { impl<'a> Iterator for LktDatabaseQueueIter<'a> {
type Item = &'a i64; type Item = i64;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let priority = self.priority?.clamp(0, LKT_DATABASE_QUEUES_COUNT - 1); let priority = self.priority?.clamp(0, LKT_DATABASE_QUEUES_COUNT - 1);
let level = &self.queue.levels[priority]; let level = &self.queue.levels[priority];
match level.get(self.index) { match level.get(self.index).copied() {
Some(ret) => { Some(ret) => {
self.index += 1; self.index += 1;
Some(ret) Some(ret)
...@@ -83,7 +85,7 @@ impl<'a> Iterator for LktDatabaseQueueIter<'a> { ...@@ -83,7 +85,7 @@ impl<'a> Iterator for LktDatabaseQueueIter<'a> {
} }
impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> { impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> {
type Item = &'a i64; type Item = i64;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let new_remaining = self.remaining.saturating_sub(1); let new_remaining = self.remaining.saturating_sub(1);
...@@ -100,27 +102,32 @@ impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> { ...@@ -100,27 +102,32 @@ impl<'a> Iterator for LktDatabaseQueueRangeIter<'a> {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct LktDatabaseQueue { pub struct LktDatabaseQueue {
levels: [VecDeque<i64>; LKT_DATABASE_QUEUES_COUNT], levels: [VecDeque<i64>; LKT_DATABASE_QUEUES_COUNT],
current: Option<i64>,
} }
impl LktDatabaseQueue { impl LktDatabaseQueue {
pub fn enqueue_kara(&mut self, local_id: i64) { /// Get the current kara in the queue.
self.levels[0].push_back(local_id); 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(); let priority: usize = priority.into();
self.levels[priority].push_back(local_id); self.levels[priority].push_back(local_id);
} }
pub fn insert_kara(&mut self, local_id: i64) { /// Add all karas in the queue with a given priority in the passed order.
self.levels[LKT_DATABASE_QUEUES_COUNT - 1].push_front(local_id); pub fn add_kara_all<I: IntoIterator<Item = i64>>(
} &mut self,
local_ids: I,
pub fn insert_kara_with_priority(&mut self, local_id: i64, priority: LktDatabasePriority) { priority: LktDatabasePriority,
) {
let priority: usize = priority.into(); 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 { pub fn iter(&self) -> LktDatabaseQueueIter {
let priority = self let priority = self
.levels .levels
...@@ -135,19 +142,25 @@ impl LktDatabaseQueue { ...@@ -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() 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> { pub fn pop_next(&mut self) -> Option<i64> {
let level = self let level = self
.levels .levels
.iter_mut() .iter_mut()
.rev() .rev()
.find(|content| !content.is_empty())?; .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 { pub fn range(&self, range: Range<usize>) -> LktDatabaseQueueRangeIter {
let mut iter = self.iter(); let mut iter = self.iter();
let remaining = range.end.saturating_sub(range.start); let remaining = range.end.saturating_sub(range.start);
...@@ -161,4 +174,34 @@ impl LktDatabaseQueue { ...@@ -161,4 +174,34 @@ impl LktDatabaseQueue {
remaining, 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!()
}
} }
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter