Daemonize the musicbrainz thread #217

Merged
wojtek merged 15 commits from 188---add-option-for-manual-input-during-fetch into main 2024-09-21 23:03:47 +02:00
3 changed files with 12 additions and 83 deletions
Showing only changes of commit 21d0034b97 - Show all commits

View File

@ -1,33 +1,18 @@
use std::{
collections::VecDeque,
sync::{
mpsc::{self, TryRecvError},
Arc, Mutex,
},
thread, time,
};
use std::{collections::VecDeque, sync::mpsc::{self, TryRecvError}};
use musichoard::collection::{
album::AlbumMeta,
artist::{Artist, ArtistMeta},
musicbrainz::{IMusicBrainzRef, Mbid},
};
use musichoard::collection::{artist::Artist, musicbrainz::IMusicBrainzRef};
use crate::tui::{
app::{
machine::{match_state::MatchState, App, AppInner, AppMachine},
AppPublicState, AppState, IAppEventFetch, IAppInteractFetch, MatchStateInfo,
},
event::{Event, EventSender},
lib::{
external::musicbrainz::daemon::{
ApiParams, Job, JobInstance, JobPriority, ReturnSender, SearchArtistParams,
SearchParams, SearchReleaseGroupParams,
},
interface::musicbrainz::{
self,
api::{Error as MbError, IMusicBrainz},
},
interface::musicbrainz::api::Error as MbError,
},
};
@ -43,7 +28,6 @@ impl FetchState {
pub type FetchError = MbError;
pub type FetchResult = Result<MatchStateInfo, FetchError>;
pub type FetchSender = mpsc::Sender<FetchResult>;
pub type FetchReceiver = mpsc::Receiver<FetchResult>;
impl AppMachine<FetchState> {
@ -115,58 +99,6 @@ impl AppMachine<FetchState> {
let job = Job::new(JobPriority::Background, JobInstance::new(tx, queue));
inner.musicbrainz.send(job);
}
fn fetch_artist(
musicbrainz: Arc<Mutex<dyn IMusicBrainz + Send>>,
fetch_tx: FetchSender,
events: EventSender,
artist: ArtistMeta,
) {
let result = musicbrainz.lock().unwrap().search_artist(&artist);
let result = result.map(|list| MatchStateInfo::artist(artist, list));
Self::send_fetch_result(&fetch_tx, &events, result).ok();
}
fn fetch_albums(
musicbrainz: Arc<Mutex<dyn IMusicBrainz + Send>>,
fetch_tx: FetchSender,
events: EventSender,
arid: Mbid,
albums: Vec<AlbumMeta>,
) {
let mut musicbrainz = musicbrainz.lock().unwrap();
let mut album_iter = albums.into_iter().peekable();
while let Some(album) = album_iter.next() {
if album.musicbrainz.is_some() {
continue;
}
let result = musicbrainz.search_release_group(&arid, &album);
let result = result.map(|list| MatchStateInfo::album(album, list));
if Self::send_fetch_result(&fetch_tx, &events, result).is_err() {
return;
};
if album_iter.peek().is_some() {
thread::sleep(time::Duration::from_secs(1));
}
}
}
fn send_fetch_result(
fetch_tx: &FetchSender,
events: &EventSender,
result: Result<MatchStateInfo, musicbrainz::api::Error>,
) -> Result<(), ()> {
// If receiver disconnects just drop the rest.
fetch_tx.send(result).map_err(|_| ())?;
// If this send fails the event listener is dead. Don't panic as this function runs in a
// detached thread so this might be happening during normal shut down.
events.send(Event::FetchResultReady).map_err(|_| ())?;
Ok(())
}
}
impl From<AppMachine<FetchState>> for App {

View File

@ -8,16 +8,14 @@ mod match_state;
mod reload_state;
mod search_state;
use std::sync::{mpsc, Arc, Mutex};
use std::sync::mpsc;
use crate::tui::{
app::{
selection::Selection, AppMode, AppPublic, AppPublicInner, AppPublicState, AppState, IApp,
IAppAccess, IAppBase, IAppState,
},
event::EventSender,
lib::{external::musicbrainz::daemon::Job, interface::musicbrainz::api::IMusicBrainz, IMusicHoard},
RequestChannel,
lib::{external::musicbrainz::daemon::Job, IMusicHoard},
};
use browse_state::BrowseState;

View File

@ -163,14 +163,14 @@ impl MusicBrainzDaemon {
api: MB,
request_receiver: mpsc::Receiver<Job>,
events: EventSender,
) {
) -> Result<(), Error> {
let daemon = MusicBrainzDaemon {
api: Box::new(api),
request_receiver,
job_queue: JobQueue::new(),
events,
};
daemon.main();
daemon.main()
}
fn wait_for_jobs(&mut self) -> Result<(), Error> {
@ -195,13 +195,12 @@ impl MusicBrainzDaemon {
}
fn execute_next_job(&mut self) -> Option<()> {
while let Some(instance) = self.job_queue.front_mut() {
match instance.execute_next(&mut self.api, &mut self.events) {
Some(()) => return Some(()),
None => {
if let Some(instance) = self.job_queue.front_mut() {
let result = instance.execute_next(&mut self.api, &mut self.events);
if result.is_none() {
self.job_queue.pop_front();
}
}
return Some(());
}
None
}