From d03ceca131f51264da24c66d93acb2e10620b796 Mon Sep 17 00:00:00 2001 From: Nuno Pereira Date: Sat, 15 Apr 2023 12:42:35 +0100 Subject: [PATCH] Added lyrics cache to LyricsManager --- src/lyrics.rs | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/lyrics.rs b/src/lyrics.rs index ef4e5ced1..294f21cdb 100644 --- a/src/lyrics.rs +++ b/src/lyrics.rs @@ -1,4 +1,5 @@ -use std::sync::Arc; +use log::trace; +use std::{cell::RefCell, collections::HashMap, sync::Arc}; use crate::{ lyrics_fetcher::LyricsFetcher, @@ -10,26 +11,52 @@ use crate::{ pub struct LyricsManager { queue: Arc, fetcher: LyricsFetcher, - // TODO: add a cache + cache: RefCell>, } impl LyricsManager { pub fn new(queue: Arc, fetcher: LyricsFetcher) -> Self { - LyricsManager { queue, fetcher } + LyricsManager { + queue, + fetcher, + cache: RefCell::new(HashMap::new()), + } } /// Saves the given lyrics to the user's filesystem. /// /// Returns an optional message indicating the outcome of this operation. pub fn save_lyrics(&self, lyrics: String) -> Option { - Some("".to_string()) + Some(lyrics) } /// Fetches and returns the lyrics of the given track pub fn get_lyrics(&self, track: Track) -> String { - // TODO: implement caching + // TODO: see if this panics later on + let track_id = track.id.as_ref().unwrap(); + + { + // insert new scope so that we can perform both borrows from the RefCell + // the immutable borrow present in this scope is dropped, + // so it is safe to do another borrow after + + let cache = self.cache.borrow(); + + if cache.contains_key(track_id) { + trace!("Retrieving cached lyrics for {}", track.title); + return cache.get(track_id).unwrap().to_owned(); + } + } + + // if we reach this point it means that the cache does not contain this entry yet, update it + let mut cache = self.cache.borrow_mut(); + + // make network request to fetch track's lyrics + let lyrics = self.fetcher.fetch(&track); + + cache.insert(track_id.to_owned(), lyrics.clone()); - self.fetcher.fetch(&track) + lyrics } /// Fetches and returns the lyrics of the currently playing track @@ -40,13 +67,13 @@ impl LyricsManager { } } - /// Returns the track being played currently, or nothing if the user is listening to a podcast episodes + /// Returns the track being played currently, or nothing if the user is listening to a podcast episode pub fn get_current_track(&self) -> Option { let playable = self.queue.get_current().unwrap(); match playable { Playable::Track(track) => Some(track), - Playable::Episode(_) => None, + _ => None, } } }