diff --git a/src/rust/amalib/Cargo.toml b/src/rust/amalib/Cargo.toml index 9cee7e7860571c0b82aba6cbbb2d4008c7c42ff8..3c68c021616dd7476f5148ad8a29bac3b6311131 100644 --- a/src/rust/amalib/Cargo.toml +++ b/src/rust/amalib/Cargo.toml @@ -9,5 +9,8 @@ license.workspace = true serde.workspace = true tokio.workspace = true +smallstring = { path = "../smallstring" } commons = { path = "../commons" } getset = { path = "../getset" } + +lru = { version = "^0.9" } diff --git a/src/rust/amalib/src/amacache.rs b/src/rust/amalib/src/amacache.rs new file mode 100644 index 0000000000000000000000000000000000000000..1b1ad27f5fdefde808dff3dc81d30e1eee5d11f5 --- /dev/null +++ b/src/rust/amalib/src/amacache.rs @@ -0,0 +1,111 @@ +use lru::LruCache; +use serde::{Deserialize, Serialize}; +use smallstring::SmallString; +use std::{collections::HashMap, num::NonZeroUsize}; + +/// Represent a global id for a kara, the pair (database, id). +#[derive(Debug, Deserialize, Serialize)] +pub struct KaraId { + pub repo: SmallString, + pub id: i64, +} + +/// Represent what we want to override in a kara. +#[derive(Debug, Deserialize, Serialize)] +pub struct KaraOverride {} + +/// A list of informations about a kara. This is the data from lektor. When +/// queried we patch it with the overrides given by the user. +#[derive(Debug)] +pub struct KaraInfo {} + +#[allow(dead_code)] +#[derive(Debug)] +pub struct Playlist { + name: SmallString, + ctime: i64, + creator: SmallString, + content: Vec<i64>, +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize, Serialize)] +#[serde(transparent)] +pub struct AmaDB { + /// Contains the content of the queue. + #[serde(skip)] + queue: Vec<i64>, + + /// We cache the database so we don't have to make requests every time we + /// refresh the queue or a playlist. + databases: AmaDBCache, +} + +/// We cache objects locally so we don't have to always make requests to +/// lektord. When we get the update stored database event from mpv we clear the +/// cache, if its the playlists that are updated, we clear only the playlist, if +/// it's the database, we clear everything. +#[allow(dead_code)] +#[derive(Debug, Deserialize, Serialize)] +struct AmaDBCache { + /// Cache requests to lektord. + #[serde(skip, default = "new_empty_kara_lru")] + lru_lektor: LruCache<i64, KaraInfo>, + + /// Cache requests to lektord that where patched. + #[serde(skip, default = "new_empty_kara_lru")] + lru_patched: LruCache<i64, KaraInfo>, + + /// The playlists. We don't save them... + #[serde(skip, default = "new_empty_playlist_lru")] + playlists: LruCache<SmallString, Playlist>, + + /// The list of overrides, indexed by the local id of the kara. + overrides: HashMap<i64, KaraOverride>, + + /// The conversion list for local id <-> repo id. Overrides are declared + /// with the repo ids because it's the only thing that every client have in + /// common. We must adapt to the local id. + local_ids: HashMap<i64, KaraId>, +} + +/// Create a new empty LRU cache. We set the value to the maximal count of +/// visible karas multiplied by a threeshold. +fn new_empty_kara_lru() -> LruCache<i64, KaraInfo> { + use crate::constants::*; + LruCache::new( + NonZeroUsize::new( + (f64::from(PINED_KARAS_MAX_COUNT) * PINED_THREESHOLD_FOR_CACHES).round() as usize, + ) + .expect("got a zero usize..."), + ) +} + +/// Create a new empty LRU cache for playlists. We set the value to the maximal +/// number of pined playlists multiplied by a threeshold. +fn new_empty_playlist_lru() -> LruCache<SmallString, Playlist> { + use crate::constants::*; + LruCache::new( + NonZeroUsize::new( + (f64::from(PINED_PLAYLISTS_MAX_COUNT) * PINED_THREESHOLD_FOR_CACHES).round() as usize, + ) + .expect("got a zero usize..."), + ) +} + +impl AmaDB { + /// Clear the database cache, and only the caches about karas. + pub fn clear_database_cache(&mut self) { + todo!() + } + + /// Clear the cache for a playlist, and only that playlist. + pub fn clear_playlist_cache<S: AsRef<str>>(&mut self, _name: S) { + todo!() + } + + /// Clear the cache for all the playlists. + pub fn clear_playlists_cache(&mut self) { + todo!() + } +} diff --git a/src/rust/amalib/src/constants.rs b/src/rust/amalib/src/constants.rs index 505f0af8e8e8bc5773341ca8fc6496988cb76508..00977f31d71660bdbccea92318689d569645ea08 100644 --- a/src/rust/amalib/src/constants.rs +++ b/src/rust/amalib/src/constants.rs @@ -20,3 +20,13 @@ pub(crate) const BUFFER_OUT_MAX: usize = 16; /// Expected version from the lektord daemin. pub(crate) const MPD_VERSION: &str = "0.21.16"; + +/// Maximal number of pined playlists. +pub const PINED_PLAYLISTS_MAX_COUNT: u16 = 16; + +/// Maximal number of visible karas at one time. +pub const PINED_KARAS_MAX_COUNT: u16 = 1000; + +/// A threeshold to not make requests at all frames when the pined max count is +/// hitted. +pub(crate) const PINED_THREESHOLD_FOR_CACHES: f64 = 1.5_f64; diff --git a/src/rust/amalib/src/lib.rs b/src/rust/amalib/src/lib.rs index 8ee7b9eb8c3e5d9cbd6f7b9b0af47086c6f8fcde..476fc5b161e4b1bf323869e31037e825260b7e7f 100644 --- a/src/rust/amalib/src/lib.rs +++ b/src/rust/amalib/src/lib.rs @@ -4,12 +4,14 @@ //! communicate with the lektord server and elements to store and organise the //! queried informations. +mod amacache; mod connexion; mod constants; mod query; mod response; mod uri; +pub use amacache::*; pub use connexion::*; pub use query::*; pub use response::*;