Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Реализован manager
Browse files Browse the repository at this point in the history
Реализован file watcher
Исправлено узкое горлышко в скачивании плагинов
  • Loading branch information
TOwInOK committed May 20, 2024
1 parent 54318b9 commit da9d304
Show file tree
Hide file tree
Showing 16 changed files with 580 additions and 95 deletions.
235 changes: 231 additions & 4 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-watcher = "0.2.1"
bytes = "1.6.0"
console = "0.15.8"
futures-util = "0.3.30"
Expand All @@ -20,4 +21,5 @@ sha1 = "0.10.6"
sha2 = "0.10.8"
thiserror = "1.0.59"
tokio = { version = "1.37.0", features = ["full"] }
tokio-util = "0.7.11"
toml = "0.8.12"
1 change: 0 additions & 1 deletion settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ version = "1.20.6"
[plugins.chunky]
[plugins.nbtapi]
[plugins.chunkyborder]
[plugins.lifestealz]
5 changes: 3 additions & 2 deletions settings_example.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Require
# Require
[core] # just core, nothing here to change :)
provider = "paper" # [vanilla, paper, folia, purpur, fabric, waterfall, velocity]
version = "1.20.6" # Or Latest (latest -> get error)
Expand All @@ -23,4 +23,5 @@ force_update = false # false || true => false by default
# Optional
[additions]
source = "[email protected]:Username/Super-Config.git" # Optional, require for key
key = "MySuperMegaKey" # Optional, don't work without link
key = "MySuperMegaKey" # Optional, don't work without link
duraction = 300 # Optional, value of duraction between manager checker iterations (in seconds)
39 changes: 35 additions & 4 deletions src/errors/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use thiserror::Error;

use crate::mananger::messages::Messages;

#[derive(Error, Debug)]
pub enum CompareHashError {
#[error("Хэш не совпадает")]
Expand All @@ -24,17 +26,46 @@ pub enum Error {
// Download(String),
#[error("Ошибка ввода/вывода: {0}")]
Io(#[from] std::io::Error),
#[error("Ошибка парсинга TOML: {0}")]
TomlParse(#[from] toml::de::Error),
#[error("{0}")]
TomlParse(String),
#[error("Ошибка сериализация TOML: {0}")]
TomlSerialize(#[from] toml::ser::Error),
#[error("Не удалось найти: {0}")]
NotFound(String),
// #[error("Ошибка: {0}")]
// Any(#[from] Box<dyn std::error::Error>),
#[error("Ошибка: {0}")]
Any(#[from] Box<dyn std::error::Error + Send>),
#[error("Task join error: {0}")]
JoinError(#[from] tokio::task::JoinError),
#[error("Indicatif template error: {0}")]
IndicatifTemplate(#[from] indicatif::style::TemplateError),
#[error("Indicatif template error: {0}")]
SendMessage(#[from] tokio::sync::mpsc::error::SendError<Messages>),
}
pub type Result<T> = std::result::Result<T, Error>;

impl From<toml::de::Error> for Error {
fn from(value: toml::de::Error) -> Self {
let value = value.to_string();
let parts: Vec<&str> = value.split('|').collect();

// Проверяем, что индексы существуют и выбираем только нужные
let message = if parts.len() >= 4 {
let third_part = parts[3].trim();
let trimmed_third_part = &third_part[2..]; // Удаляем первые три символа
format!(
" Where => {} ||| What => {} ||| why => {} ",
parts[0].trim(),
parts[2].trim(),
trimmed_third_part
)
} else {
value.to_string() // Если не удалось разделить на нужное количество частей, вернем исходную строку
};

Error::TomlParse(message)
}
}

#[macro_export]
macro_rules! not_found {
($msg:expr) => {
Expand Down
3 changes: 2 additions & 1 deletion src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod core;
pub mod ext;

use serde::{Deserialize, Serialize};
use tokio::sync::RwLockReadGuard;

use self::core::CoreMeta;
use self::ext::ExtensionMeta;
Expand Down Expand Up @@ -47,7 +48,7 @@ impl Lock {
self.core = CoreMeta::default();
Ok(())
}
pub fn remove_nonexistent(&mut self, settings: &Settings) -> Result<()> {
pub fn remove_nonexistent(&mut self, settings: RwLockReadGuard<Settings>) -> Result<()> {
let plugin_keys: Vec<String> = self.plugins().0.keys().cloned().collect();
// TODO: let mods_keys
if let Some(e) = settings.plugins() {
Expand Down
61 changes: 2 additions & 59 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,74 +1,17 @@
pub mod errors;
pub mod lock;
pub mod mananger;
pub mod models;
pub mod query;
pub mod settings;
pub mod tr;

use std::sync::Arc;

use crate::errors::error::Result;
use indicatif::{MultiProgress, ProgressBar};
use lock::Lock;
use log::warn;
use settings::Settings;
use tokio::sync::Mutex;
use tr::load::Load;

#[tokio::main]
async fn main() -> Result<()> {
pretty_env_logger::formatted_builder()
.filter_level(log::LevelFilter::Info)
.init();
// Init
let (mpb, lock, settings) = init().await;
//
let pb = mpb.add(ProgressBar::new_spinner());
pb.finish_with_message("Init Minecraft Addon Controller");
//
lock.lock().await.remove_nonexistent(&settings)?;
'_c: {
let lock = Arc::clone(&lock);
let settings = Arc::clone(&settings);
let mpb = Arc::clone(&mpb);
download(settings, lock, mpb).await?;
}
Ok(())
}

async fn download(
settings: Arc<Settings>,
lock: Arc<Mutex<Lock>>,
mpb: Arc<MultiProgress>,
) -> Result<()> {
'_core_scope: {
let lock = Arc::clone(&lock);
let mpb = Arc::clone(&mpb);
settings.core().download(lock, mpb).await?;
}
'_plugins_scope: {
let lock = Arc::clone(&lock);
let mpb = Arc::clone(&mpb);
if let Some(plugins) = settings.plugins() {
plugins
.download_all(
settings.core().provider().as_str(),
settings.core().version(),
lock,
mpb,
)
.await?;
}
}
Ok(())
}

async fn init() -> (Arc<MultiProgress>, Arc<Mutex<Lock>>, Arc<Settings>) {
let mpb: Arc<MultiProgress> = Arc::new(MultiProgress::new());
let lock: Arc<Mutex<Lock>> = Arc::new(Mutex::new(Lock::load().await.unwrap_or({
warn!("Use default Lock");
Lock::default()
})));
let settings: Arc<Settings> = Arc::new(Settings::load().await.unwrap());
(mpb, lock, settings)
mananger::run().await
}
63 changes: 63 additions & 0 deletions src/mananger/download.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::sync::Arc;
use std::time::Duration;

use indicatif::MultiProgress;
use tokio::sync::{Mutex, RwLock};
use tokio::time::sleep;
use tokio_util::sync::CancellationToken;

use crate::errors::error::Result;
use crate::settings::additions::Additions;
use crate::{lock::Lock, settings::Settings};

pub async fn download(
settings: Arc<RwLock<Settings>>,
lock: Arc<Mutex<Lock>>,
mpb: Arc<MultiProgress>,
key: Arc<CancellationToken>,
) -> Result<()> {
let duraction = settings
.read()
.await
.additions()
.unwrap_or(&Additions::default())
.duraction()
.unwrap_or(300f64);
let cooldown = Duration::from_secs_f64(duraction);
loop {
'_core_scope: {
let lock = Arc::clone(&lock);
let settings = Arc::clone(&settings);
let mpb = Arc::clone(&mpb);
tokio::spawn(async move {
let settings = settings.read().await;
settings.core().download(lock, mpb).await
});
}
'_plugins_scope: {
let lock = Arc::clone(&lock);
let settings = Arc::clone(&settings);
let mpb = Arc::clone(&mpb);

tokio::spawn(async move {
let settings = settings.read().await;
if let Some(plugins) = settings.plugins() {
plugins
.download_all(
settings.core().provider().as_str(),
settings.core().version(),
lock,
mpb,
)
.await
} else {
Ok(())
}
});
};
tokio::select! {
_ = sleep(cooldown) => {},
_ = key.cancelled() => {break Ok(())},
}
}
}
52 changes: 52 additions & 0 deletions src/mananger/manage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::sync::Arc;

use indicatif::MultiProgress;
use tokio::sync::{mpsc::Receiver, Mutex, RwLock};
use tokio_util::sync::CancellationToken;

use crate::errors::error::Result;
use crate::mananger::download::download;
use crate::mananger::messages::Messages;
use crate::{lock::Lock, settings::Settings};

pub async fn manage(
mut rx: Receiver<Messages>,
lock: Arc<Mutex<Lock>>,
settings: Arc<RwLock<Settings>>,
mpb: Arc<MultiProgress>,
) -> Result<()> {
loop {
let lock = Arc::clone(&lock);
let settings = Arc::clone(&settings);
let mpb = Arc::clone(&mpb);
let key = Arc::new(CancellationToken::new());
tokio::select! {
Some(e) = rx.recv() => match e {
Messages::Restart(pb) => {
pb.set_message("Рестарт!");
let key = Arc::clone(&key);
pb.set_message("Стопаем текущюю задачу!");
key.cancel();
mpb.clear()?;
if key.is_cancelled() {
pb.set_message("Начинаем новую!");
tokio::spawn(download(settings.clone(), lock.clone(), mpb.clone(), key));
} else {
pb.set_message("Ну... она стоит");
}
pb.finish_and_clear();
}
Messages::Stop(pb) => {
pb.finish_with_message("Остановка!");
key.cancelled().await;
}
Messages::Start(pb) => {
let key = Arc::clone(&key);
pb.finish_with_message("Начинаем новую!");
tokio::spawn(download(settings.clone(), lock.clone(), mpb.clone(), key));
pb.finish_and_clear();
}
},
}
}
}
9 changes: 9 additions & 0 deletions src/mananger/messages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::sync::Arc;

use indicatif::ProgressBar;

pub enum Messages {
Restart(Arc<ProgressBar>),
Stop(Arc<ProgressBar>),
Start(Arc<ProgressBar>),
}
60 changes: 60 additions & 0 deletions src/mananger/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
mod download;
mod manage;
pub mod messages;
mod watch_changer;

use std::sync::Arc;

use crate::errors::error::Result;
use indicatif::{MultiProgress, ProgressBar};
use lock::Lock;
use log::warn;
use manage::manage;
use settings::Settings;
use tokio::{
sync::{mpsc, Mutex, RwLock},
try_join,
};
use tr::load::Load;

use crate::{lock, settings, tr};

use self::watch_changer::watch_changes;

pub async fn run() -> Result<()> {
let (mpb, lock, settings) = init().await?;
//
let pb = mpb.add(ProgressBar::new_spinner());
pb.finish_with_message("Init Minecraft Addon Controller");
//
let (tx, rx) = mpsc::channel(20);

let manage = {
let settings_m = Arc::clone(&settings);
let lock = Arc::clone(&lock);
let mpb_m = Arc::clone(&mpb);
manage(rx, lock, settings_m, mpb_m)
};
let watch_changes = {
let settings_w = Arc::clone(&settings);
let lock = Arc::clone(&lock);
let mpb_w = Arc::clone(&mpb);
watch_changes(settings_w, lock, mpb_w, tx)
};

let a = try_join!(manage, watch_changes);
match a {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}

async fn init() -> Result<(Arc<MultiProgress>, Arc<Mutex<Lock>>, Arc<RwLock<Settings>>)> {
let mpb: Arc<MultiProgress> = Arc::new(MultiProgress::new());
let lock: Arc<Mutex<Lock>> = Arc::new(Mutex::new(Lock::load().await.unwrap_or({
warn!("Use default Lock");
Lock::default()
})));
let settings = Arc::new(RwLock::new(Settings::load().await?));
Ok((mpb, lock, settings))
}
Loading

0 comments on commit da9d304

Please sign in to comment.