mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-13 08:12:44 +10:00
feat(downloads): Added AgentInterfaceData to get information about all downloads in queue
Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
@ -26,7 +26,7 @@ async function startGameDownload() {
|
||||
setInterval(() => {
|
||||
(async () => {
|
||||
const currentProgress = await invoke<number>(
|
||||
"get_game_download_progress",
|
||||
"get_current_game_download_progress",
|
||||
{
|
||||
gameId: gameId.value,
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ pub struct GameDownloadAgent {
|
||||
pub progress: ProgressObject,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum GameDownloadError {
|
||||
CommunicationError(RemoteAccessError),
|
||||
ChecksumError,
|
||||
@ -50,11 +50,11 @@ impl Display for GameDownloadError {
|
||||
impl GameDownloadAgent {
|
||||
pub fn new(id: String, version: String, target_download_dir: usize) -> Self {
|
||||
// Don't run by default
|
||||
let status = DownloadThreadControl::new(DownloadThreadControlFlag::Stop);
|
||||
let control_flag = DownloadThreadControl::new(DownloadThreadControlFlag::Stop);
|
||||
Self {
|
||||
id,
|
||||
version,
|
||||
control_flag: status.clone(),
|
||||
control_flag,
|
||||
manifest: Mutex::new(None),
|
||||
target_download_dir,
|
||||
contexts: Mutex::new(Vec::new()),
|
||||
@ -207,6 +207,7 @@ impl GameDownloadAgent {
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
||||
pool.scope(move |scope| {
|
||||
let contexts = self.contexts.lock().unwrap();
|
||||
|
||||
|
||||
@ -36,17 +36,9 @@ pub fn download_game(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_game_download_progress(
|
||||
pub fn get_current_game_download_progress(
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
game_id: String,
|
||||
) -> Result<f64, String> {
|
||||
/*
|
||||
let download_agent = use_download_agent(state, game_id)?;
|
||||
|
||||
let progress = &download_agent.progress;
|
||||
|
||||
Ok(progress.get_progress())
|
||||
*/
|
||||
let progress = state
|
||||
.lock()
|
||||
.unwrap()
|
||||
|
||||
@ -148,7 +148,7 @@ pub fn download_game_chunk(
|
||||
.get(chunk_url)
|
||||
.header("Authorization", header)
|
||||
.send()
|
||||
.map_err(|e| GameDownloadError::CommunicationError(RemoteAccessError::FetchError(e)))?;
|
||||
.map_err(|e| GameDownloadError::CommunicationError(e.into()))?;
|
||||
|
||||
let mut destination = DropWriter::new(ctx.path);
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ use std::{
|
||||
use log::info;
|
||||
|
||||
use super::{
|
||||
download_agent::GameDownloadAgent,
|
||||
download_manager_interface::DownloadManagerInterface,
|
||||
download_agent::{GameDownloadAgent, GameDownloadError},
|
||||
download_manager_interface::{AgentInterfaceData, DownloadManagerInterface},
|
||||
download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag},
|
||||
progress_object::ProgressObject,
|
||||
};
|
||||
@ -55,12 +55,13 @@ Behold, my madness - quexeky
|
||||
|
||||
pub struct DownloadManager {
|
||||
download_agent_registry: HashMap<String, Arc<GameDownloadAgent>>,
|
||||
download_queue: Arc<Mutex<VecDeque<String>>>,
|
||||
download_queue: Arc<Mutex<VecDeque<Arc<AgentInterfaceData>>>>,
|
||||
command_receiver: Receiver<DownloadManagerSignal>,
|
||||
sender: Sender<DownloadManagerSignal>,
|
||||
progress: Arc<Mutex<Option<ProgressObject>>>,
|
||||
status: Arc<Mutex<DownloadManagerStatus>>,
|
||||
|
||||
current_game_id: Option<String>, // Should be the only game download agent in the map with the "Go" flag
|
||||
current_game_interface: Option<Arc<AgentInterfaceData>>, // Should be the only game download agent in the map with the "Go" flag
|
||||
active_control_flag: Option<DownloadThreadControl>,
|
||||
}
|
||||
pub enum DownloadManagerSignal {
|
||||
@ -77,6 +78,21 @@ pub enum DownloadManagerSignal {
|
||||
/// Tells the Manager to stop the current
|
||||
/// download and return
|
||||
Finish,
|
||||
/// Any error which occurs in the agent
|
||||
Error(GameDownloadError)
|
||||
}
|
||||
pub enum DownloadManagerStatus {
|
||||
Downloading,
|
||||
Paused,
|
||||
Empty,
|
||||
Error(GameDownloadError),
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub enum GameDownloadStatus {
|
||||
Downloading,
|
||||
Paused,
|
||||
Uninitialised,
|
||||
Error(GameDownloadError),
|
||||
}
|
||||
|
||||
impl DownloadManager {
|
||||
@ -84,13 +100,15 @@ impl DownloadManager {
|
||||
let queue = Arc::new(Mutex::new(VecDeque::new()));
|
||||
let (command_sender, command_receiver) = channel();
|
||||
let active_progress = Arc::new(Mutex::new(None));
|
||||
let status = Arc::new(Mutex::new(DownloadManagerStatus::Empty));
|
||||
|
||||
let manager = Self {
|
||||
download_agent_registry: HashMap::new(),
|
||||
download_queue: queue.clone(),
|
||||
command_receiver,
|
||||
current_game_id: None,
|
||||
current_game_interface: None,
|
||||
active_control_flag: None,
|
||||
status: status.clone(),
|
||||
sender: command_sender.clone(),
|
||||
progress: active_progress.clone(),
|
||||
};
|
||||
@ -110,6 +128,7 @@ impl DownloadManager {
|
||||
match signal {
|
||||
DownloadManagerSignal::Go => {
|
||||
self.manage_go_signal();
|
||||
|
||||
}
|
||||
DownloadManagerSignal::Stop => {
|
||||
self.manage_stop_signal();
|
||||
@ -129,6 +148,9 @@ impl DownloadManager {
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
DownloadManagerSignal::Error(game_download_error) => {
|
||||
self.manage_error_signal(game_download_error);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -142,13 +164,16 @@ impl DownloadManager {
|
||||
|
||||
fn manage_completed_signal(&mut self, game_id: String) {
|
||||
info!("Got signal 'Completed'");
|
||||
if self.current_game_id == Some(game_id.clone()) {
|
||||
if let Some(interface) = &self.current_game_interface {
|
||||
// When if let chains are stabilised, combine these two statements
|
||||
if interface.id == game_id {
|
||||
info!("Popping consumed data");
|
||||
self.download_queue.lock().unwrap().pop_front();
|
||||
self.download_agent_registry.remove(&game_id);
|
||||
self.active_control_flag = None;
|
||||
*self.progress.lock().unwrap() = None;
|
||||
}
|
||||
}
|
||||
self.sender.send(DownloadManagerSignal::Go).unwrap();
|
||||
}
|
||||
|
||||
@ -164,9 +189,14 @@ impl DownloadManager {
|
||||
version,
|
||||
target_download_dir,
|
||||
));
|
||||
let agent_status = GameDownloadStatus::Uninitialised;
|
||||
let interface_data = Arc::new(AgentInterfaceData {
|
||||
id,
|
||||
status: Mutex::new(agent_status),
|
||||
});
|
||||
self.download_agent_registry
|
||||
.insert(id.clone(), download_agent);
|
||||
self.download_queue.lock().unwrap().push_back(id);
|
||||
.insert(interface_data.id.clone(), download_agent);
|
||||
self.download_queue.lock().unwrap().push_back(interface_data);
|
||||
}
|
||||
|
||||
fn manage_go_signal(&mut self) {
|
||||
@ -176,11 +206,12 @@ impl DownloadManager {
|
||||
let download_agent = {
|
||||
let lock = self.download_queue.lock().unwrap();
|
||||
self.download_agent_registry
|
||||
.get(&lock.front().unwrap().clone())
|
||||
.get(&lock.front().unwrap().id)
|
||||
.unwrap()
|
||||
.clone()
|
||||
};
|
||||
self.current_game_id = Some(download_agent.id.clone());
|
||||
let download_agent_interface = Arc::new(AgentInterfaceData::from(download_agent.clone()));
|
||||
self.current_game_interface = Some(download_agent_interface);
|
||||
|
||||
let progress_object = download_agent.progress.clone();
|
||||
*self.progress.lock().unwrap() = Some(progress_object);
|
||||
@ -192,14 +223,20 @@ impl DownloadManager {
|
||||
|
||||
info!("Spawning download");
|
||||
spawn(move || {
|
||||
download_agent.download().unwrap();
|
||||
sender
|
||||
.send(DownloadManagerSignal::Completed(download_agent.id.clone()))
|
||||
.unwrap();
|
||||
let signal = match download_agent.download() {
|
||||
Ok(_) => {
|
||||
DownloadManagerSignal::Completed(download_agent.id.clone())
|
||||
},
|
||||
Err(e) => {
|
||||
DownloadManagerSignal::Error(e)
|
||||
},
|
||||
};
|
||||
sender.send(signal).unwrap();
|
||||
});
|
||||
info!("Finished spawning Download");
|
||||
|
||||
active_control_flag.set(DownloadThreadControlFlag::Go);
|
||||
self.set_status(DownloadManagerStatus::Downloading);
|
||||
} else if let Some(active_control_flag) = self.active_control_flag.clone() {
|
||||
info!("Restarting current download");
|
||||
active_control_flag.set(DownloadThreadControlFlag::Go);
|
||||
@ -207,4 +244,13 @@ impl DownloadManager {
|
||||
info!("Nothing was set");
|
||||
}
|
||||
}
|
||||
fn manage_error_signal(&self, error: GameDownloadError) {
|
||||
let current_status = self.current_game_interface.clone().unwrap();
|
||||
let mut lock = current_status.status.lock().unwrap();
|
||||
*lock = GameDownloadStatus::Error(error.clone());
|
||||
self.set_status(DownloadManagerStatus::Error(error));
|
||||
}
|
||||
fn set_status(&self, status: DownloadManagerStatus) {
|
||||
*self.status.lock().unwrap() = status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ use std::{
|
||||
|
||||
use log::info;
|
||||
|
||||
use super::{download_manager::DownloadManagerSignal, progress_object::ProgressObject};
|
||||
use super::{download_agent::GameDownloadAgent, download_manager::{DownloadManagerSignal, DownloadManagerStatus, GameDownloadStatus}, progress_object::ProgressObject};
|
||||
|
||||
/// Accessible front-end for the DownloadManager
|
||||
///
|
||||
@ -21,15 +21,27 @@ use super::{download_manager::DownloadManagerSignal, progress_object::ProgressOb
|
||||
/// THIS EDITING IS BLOCKING!!!
|
||||
pub struct DownloadManagerInterface {
|
||||
terminator: JoinHandle<Result<(), ()>>,
|
||||
download_queue: Arc<Mutex<VecDeque<String>>>,
|
||||
download_queue: Arc<Mutex<VecDeque<Arc<AgentInterfaceData>>>>,
|
||||
progress: Arc<Mutex<Option<ProgressObject>>>,
|
||||
command_sender: Sender<DownloadManagerSignal>,
|
||||
}
|
||||
pub struct AgentInterfaceData {
|
||||
pub id: String,
|
||||
pub status: Mutex<GameDownloadStatus>,
|
||||
}
|
||||
impl From<Arc<GameDownloadAgent>> for AgentInterfaceData {
|
||||
fn from(value: Arc<GameDownloadAgent>) -> Self {
|
||||
Self {
|
||||
id: value.id.clone(),
|
||||
status: Mutex::from(GameDownloadStatus::Uninitialised)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DownloadManagerInterface {
|
||||
pub fn new(
|
||||
terminator: JoinHandle<Result<(), ()>>,
|
||||
download_queue: Arc<Mutex<VecDeque<String>>>,
|
||||
download_queue: Arc<Mutex<VecDeque<Arc<AgentInterfaceData>>>>,
|
||||
progress: Arc<Mutex<Option<ProgressObject>>>,
|
||||
command_sender: Sender<DownloadManagerSignal>,
|
||||
) -> Self {
|
||||
@ -55,9 +67,12 @@ impl DownloadManagerInterface {
|
||||
))?;
|
||||
self.command_sender.send(DownloadManagerSignal::Go)
|
||||
}
|
||||
pub fn edit(&self) -> MutexGuard<'_, VecDeque<String>> {
|
||||
pub fn edit(&self) -> MutexGuard<'_, VecDeque<Arc<AgentInterfaceData>>> {
|
||||
self.download_queue.lock().unwrap()
|
||||
}
|
||||
pub fn read_queue(&self) -> VecDeque<Arc<AgentInterfaceData>> {
|
||||
self.download_queue.lock().unwrap().clone()
|
||||
}
|
||||
pub fn get_current_game_download_progress(&self) -> Option<f64> {
|
||||
let progress_object = (*self.progress.lock().unwrap()).clone()?;
|
||||
Some(progress_object.get_progress())
|
||||
@ -95,8 +110,8 @@ impl DownloadManagerInterface {
|
||||
|
||||
/// Takes in the locked value from .edit() and attempts to
|
||||
/// get the index of whatever game_id is passed in
|
||||
fn get_index_from_id(queue: &mut MutexGuard<'_, VecDeque<String>>, id: String) -> Option<usize> {
|
||||
fn get_index_from_id(queue: &mut MutexGuard<'_, VecDeque<Arc<AgentInterfaceData>>>, id: String) -> Option<usize> {
|
||||
queue
|
||||
.iter()
|
||||
.position(|download_agent| download_agent == &id)
|
||||
.position(|download_agent| download_agent.id == id)
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ pub fn run() {
|
||||
add_new_download_dir,
|
||||
// Downloads
|
||||
download_game,
|
||||
get_game_download_progress,
|
||||
get_current_game_download_progress,
|
||||
])
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.setup(|app| {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
sync::Mutex,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use log::{info, warn};
|
||||
@ -9,9 +9,9 @@ use url::{ParseError, Url};
|
||||
|
||||
use crate::{AppState, AppStatus, DB};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RemoteAccessError {
|
||||
FetchError(reqwest::Error),
|
||||
FetchError(Arc<reqwest::Error>),
|
||||
ParsingError(ParseError),
|
||||
InvalidCodeError(u16),
|
||||
GenericErrror(String),
|
||||
@ -32,7 +32,7 @@ impl Display for RemoteAccessError {
|
||||
|
||||
impl From<reqwest::Error> for RemoteAccessError {
|
||||
fn from(err: reqwest::Error) -> Self {
|
||||
RemoteAccessError::FetchError(err)
|
||||
RemoteAccessError::FetchError(Arc::new(err))
|
||||
}
|
||||
}
|
||||
impl From<String> for RemoteAccessError {
|
||||
|
||||
Reference in New Issue
Block a user