From 625f4bd0065824e6bf14d8e079a5e56ea845c2bd Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Wed, 18 Sep 2024 21:19:59 -0700 Subject: [PATCH] Adds seed support to get_random_albums --- src/app/index.rs | 11 +++++++++-- src/app/index/collection.rs | 28 ++++++++++++++++++++++------ src/server/axum/api.rs | 14 ++++++++++---- src/server/dto/v8.rs | 7 +++++++ 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/app/index.rs b/src/app/index.rs index ce2501a..c37e29b 100644 --- a/src/app/index.rs +++ b/src/app/index.rs @@ -178,12 +178,19 @@ impl Manager { .unwrap() } - pub async fn get_random_albums(&self, count: usize) -> Result, Error> { + pub async fn get_random_albums( + &self, + seed: Option, + offset: usize, + count: usize, + ) -> Result, Error> { spawn_blocking({ let index_manager = self.clone(); move || { let index = index_manager.index.read().unwrap(); - Ok(index.collection.get_random_albums(&index.strings, count)) + Ok(index + .collection + .get_random_albums(&index.strings, seed, offset, count)) } }) .await diff --git a/src/app/index/collection.rs b/src/app/index/collection.rs index 57585ae..26d9301 100644 --- a/src/app/index/collection.rs +++ b/src/app/index/collection.rs @@ -5,7 +5,7 @@ use std::{ }; use lasso2::{Rodeo, RodeoReader, Spur}; -use rand::{rngs::ThreadRng, seq::IteratorRandom}; +use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; use serde::{Deserialize, Serialize}; use tinyvec::TinyVec; use unicase::UniCase; @@ -140,11 +140,27 @@ impl Collection { }) } - pub fn get_random_albums(&self, strings: &RodeoReader, count: usize) -> Vec { - self.albums - .keys() - .choose_multiple(&mut ThreadRng::default(), count) + pub fn get_random_albums( + &self, + strings: &RodeoReader, + seed: Option, + offset: usize, + count: usize, + ) -> Vec { + let shuffled = { + let mut rng = match seed { + Some(seed) => StdRng::seed_from_u64(seed), + None => StdRng::from_entropy(), + }; + let mut s = self.albums.keys().collect::>(); + s.shuffle(&mut rng); + s + }; + + shuffled .into_iter() + .skip(offset) + .take(count) .filter_map(|k| self.get_album(strings, k.clone())) .collect() } @@ -545,7 +561,7 @@ mod test { }, ])); - let albums = collection.get_random_albums(&strings, 10); + let albums = collection.get_random_albums(&strings, None, 0, 10); assert_eq!(albums.len(), 2); assert_eq!( diff --git a/src/server/axum/api.rs b/src/server/axum/api.rs index 52134c3..9a4d0ac 100644 --- a/src/server/axum/api.rs +++ b/src/server/axum/api.rs @@ -478,8 +478,14 @@ async fn get_random_albums( _auth: Auth, api_version: APIMajorVersion, State(index_manager): State, + Query(options): Query, ) -> Response { - let albums = match index_manager.get_random_albums(20).await { + let offset = options.offset.unwrap_or(0); + let count = options.count.unwrap_or(20); + let albums = match index_manager + .get_random_albums(options.seed, offset, count) + .await + { Ok(d) => d, Err(e) => return APIError::from(e).into_response(), }; @@ -490,10 +496,10 @@ async fn get_recent_albums( _auth: Auth, api_version: APIMajorVersion, State(index_manager): State, - Query(option): Query, + Query(options): Query, ) -> Response { - let offset = option.offset.unwrap_or(0); - let count = option.count.unwrap_or(20); + let offset = options.offset.unwrap_or(0); + let count = options.count.unwrap_or(20); let albums = match index_manager.get_recent_albums(offset, count).await { Ok(d) => d, Err(e) => return APIError::from(e).into_response(), diff --git a/src/server/dto/v8.rs b/src/server/dto/v8.rs index 26f1853..8e18ea9 100644 --- a/src/server/dto/v8.rs +++ b/src/server/dto/v8.rs @@ -436,6 +436,13 @@ pub struct GetSongsBulkOutput { pub not_found: Vec, } +#[derive(Clone, Serialize, Deserialize)] +pub struct GetRandomAlbumsParameters { + pub seed: Option, + pub offset: Option, + pub count: Option, +} + #[derive(Clone, Serialize, Deserialize)] pub struct GetRecentAlbumsParameters { pub offset: Option,