feat: console for log, input token field, better logic for running XvB process

This commit is contained in:
Louis-Marie Baer 2024-03-12 23:26:08 +01:00
parent 71c923f979
commit 6797bdd173
11 changed files with 294 additions and 160 deletions

View file

@ -11,7 +11,7 @@
- [x] logo
- [x] link to website
- [ ] message overing explaining registration and needs to read the rules.
- [ ] token input
- [x] token input
- [ ] hero checkbox
- [ ] log section
- [ ] status of h/s received by the raffle, authentication by token.
@ -19,13 +19,14 @@
- [ ] number of failures
- [ ] round type in
- [ ] win or loose
- [x] state of XvB process
- [ ] new process for XvB
- [x] status process XvB
- [x] public information from [API](https://xmrvsbeast.com/p2pool/stats)
- [x] stop, start, restart buttons
- [x] button to autostart
- [ ] distribute hashrate conforming to the algorithm.
- [ ] output log to console in XvB tab
- [x] output log to console in XvB tab
- [ ] edit metadata of project
- [ ] cargo package metadata
- [ ] pgp signatures

View file

@ -93,6 +93,13 @@ impl eframe::App for App {
xmrig_is_alive,
xvb_is_alive,
);
self.middle_panel(ctx, frame, key, p2pool_is_alive, xmrig_is_alive);
self.middle_panel(
ctx,
frame,
key,
p2pool_is_alive,
xmrig_is_alive,
xvb_is_alive,
);
}
}

View file

@ -342,7 +342,7 @@ impl crate::app::App {
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Stop P2Pool");
});
// Check if address is okay before allowing to start.
// Check if address and path is okay before allowing to start.
let mut text = String::new();
let mut ui_enabled = true;
if !Regexes::addr_ok(&self.state.p2pool.address) {
@ -556,8 +556,10 @@ impl crate::app::App {
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Stop Xvb");
});
let ui_enabled =
!self.state.p2pool.address.is_empty() && !self.state.xvb.token.is_empty();
// verify that address and token syntaxes are correct
let ui_enabled = Regexes::addr_ok(&self.state.p2pool.address)
&& self.state.xvb.token.len() == 9
&& self.state.xvb.token.parse::<u32>().is_ok();
ui.set_enabled(ui_enabled);
let color = if ui_enabled { GREEN } else { RED };
if (ui_enabled && key.is_up() && !wants_input)
@ -575,57 +577,86 @@ impl crate::app::App {
}
fn status_p2pool(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(GREEN)))
.on_hover_text(P2POOL_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(GRAY)))
.on_hover_text(P2POOL_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(RED)))
.on_hover_text(P2POOL_FAILED),
Syncing => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(ORANGE)))
.on_hover_text(P2POOL_SYNCING),
Middle | Waiting | NotMining => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(YELLOW)))
.on_hover_text(P2POOL_MIDDLE),
let color;
let hover_text = match state {
Alive => {
color = GREEN;
P2POOL_ALIVE
}
Dead => {
color = GRAY;
P2POOL_DEAD
}
Failed => {
color = RED;
P2POOL_FAILED
}
Syncing => {
color = ORANGE;
P2POOL_SYNCING
}
Middle | Waiting | NotMining => {
color = YELLOW;
P2POOL_MIDDLE
}
};
status(ui, color, hover_text, size, "P2pool ⏺");
}
fn status_xmrig(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(GREEN)))
.on_hover_text(XMRIG_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(GRAY)))
.on_hover_text(XMRIG_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(RED)))
.on_hover_text(XMRIG_FAILED),
NotMining => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(ORANGE)))
.on_hover_text(XMRIG_NOT_MINING),
Middle | Waiting | Syncing => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(YELLOW)))
.on_hover_text(XMRIG_MIDDLE),
let color;
let hover_text = match state {
Alive => {
color = GREEN;
XMRIG_ALIVE
}
Dead => {
color = GRAY;
XMRIG_DEAD
}
Failed => {
color = RED;
XMRIG_FAILED
}
NotMining => {
color = ORANGE;
XMRIG_NOT_MINING
}
Middle | Waiting | Syncing => {
color = YELLOW;
XMRIG_MIDDLE
}
};
status(ui, color, hover_text, size, "XMRig ⏺");
}
fn status_xvb(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(GREEN)))
.on_hover_text(XVB_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(GRAY)))
.on_hover_text(XVB_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(RED)))
.on_hover_text(XVB_FAILED),
Middle | Waiting | NotMining | Syncing => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(YELLOW)))
.on_hover_text(XVB_MIDDLE),
let color;
let hover_text = match state {
Alive => {
color = GREEN;
XVB_ALIVE
}
Dead => {
color = GRAY;
XVB_DEAD
}
Failed => {
color = RED;
XVB_FAILED
}
NotMining => {
color = ORANGE;
XVB_PUBLIC_ONLY
}
Middle | Waiting | Syncing => {
color = YELLOW;
XVB_MIDDLE
}
};
status(ui, color, hover_text, size, "XvB ⏺");
}
fn status(ui: &mut Ui, color: Color32, hover_text: &str, size: Vec2, text: &str) {
ui.add_sized(size, Label::new(RichText::new(text).color(color)))
.on_hover_text(hover_text);
}

View file

@ -19,6 +19,7 @@ impl crate::app::App {
key: KeyPressed,
p2pool_is_alive: bool,
xmrig_is_alive: bool,
xvb_is_alive: bool,
) {
// Middle panel, contents of the [Tab]
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
@ -144,7 +145,7 @@ path_xmr: {:#?}\n
}
Tab::Status => {
debug!("App | Entering [Status] Tab");
crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.xvb_api,&self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.size, ctx, ui);
crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.xvb_api,&self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, xvb_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.size, ctx, ui);
}
Tab::Gupax => {
debug!("App | Entering [Gupax] Tab");
@ -160,7 +161,7 @@ path_xmr: {:#?}\n
}
Tab::Xvb => {
debug!("App | Entering [XvB] Tab");
crate::disk::state::Xvb::show(self.size, ctx, ui, &self.xvb_api);
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, ctx, ui, &self.xvb_api);
}
}
});

View file

@ -46,6 +46,7 @@ impl Status {
xmrig_img: &Arc<Mutex<ImgXmrig>>,
p2pool_alive: bool,
xmrig_alive: bool,
xvb_alive: bool,
max_threads: usize,
gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>,
benchmarks: &[Benchmark],
@ -65,6 +66,7 @@ impl Status {
xmrig_alive,
xmrig_api,
xmrig_img,
xvb_alive,
xvb_api,
max_threads,
);

View file

@ -25,6 +25,7 @@ impl Status {
xmrig_alive: bool,
xmrig_api: &Arc<Mutex<PubXmrigApi>>,
xmrig_img: &Arc<Mutex<ImgXmrig>>,
xvb_alive: bool,
xvb_api: &Arc<Mutex<PubXvbApi>>,
max_threads: usize,
) {
@ -56,7 +57,7 @@ impl Status {
max_threads,
);
// [XvB]
xvb(ui, min_height, width, height, xvb_api);
xvb(ui, min_height, width, height, xvb_alive, xvb_api);
});
}
}
@ -351,11 +352,17 @@ fn xmrig(
});
}
fn xvb(ui: &mut Ui, min_height: f32, width: f32, height: f32, xvb_api: &Arc<Mutex<PubXvbApi>>) {
fn xvb(
ui: &mut Ui,
min_height: f32,
width: f32,
height: f32,
xvb_alive: bool,
xvb_api: &Arc<Mutex<PubXvbApi>>,
) {
//
let api = lock!(xvb_api);
// if this field is empty, it means nothing was received from the API.
let enabled = !api.reward_yearly.is_empty();
let enabled = xvb_alive;
ScrollArea::vertical().show(ui, |ui| {
ui.group(|ui| {
ui.vertical(|ui| {

View file

@ -1,10 +1,11 @@
use std::sync::{Arc, Mutex};
use egui::TextStyle::Name;
use egui::{Hyperlink, Image, TextEdit, Vec2};
use egui::{Hyperlink, Image, Label, RichText, TextEdit, Vec2};
use log::debug;
use crate::helper::xvb::PubXvbApi;
use crate::utils::constants::{GREEN, LIGHT_GRAY, RED, XVB_HELP, XVB_TOKEN_LEN};
use crate::utils::macros::lock;
use crate::{
constants::{BYTES_XVB, SPACE},
@ -13,11 +14,16 @@ use crate::{
impl crate::disk::state::Xvb {
#[inline(always)] // called once
pub fn show(size: Vec2, _ctx: &egui::Context, ui: &mut egui::Ui, api: &Arc<Mutex<PubXvbApi>>) {
pub fn show(
&mut self,
size: Vec2,
_ctx: &egui::Context,
ui: &mut egui::Ui,
api: &Arc<Mutex<PubXvbApi>>,
) {
let website_height = size.y / 10.0;
// let width = size.x - SPACE;
// let height = size.y - SPACE;
let height = size.y;
let width = size.x;
let text_edit = size.y / 25.0;
// logo and website link
@ -50,8 +56,37 @@ impl crate::disk::state::Xvb {
);
});
});
// address check
// input token
});
// input token
let len_token = format!("{}", self.token.len());
let text_check;
let color;
if self.token.is_empty() {
text_check = format!("[{}/{}] ", len_token, XVB_TOKEN_LEN);
color = LIGHT_GRAY;
} else if self.token.parse::<u32>().is_ok() && self.token.len() < XVB_TOKEN_LEN {
text_check = format!("[{}/{}] ", len_token, XVB_TOKEN_LEN);
color = GREEN;
} else if self.token.parse::<u32>().is_ok() && self.token.len() == XVB_TOKEN_LEN {
text_check = "".to_string();
color = GREEN;
} else {
text_check = format!("[{}/{}] ❌", len_token, XVB_TOKEN_LEN);
color = RED;
}
ui.group(|ui| {
let width = width - SPACE;
ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0);
ui.label("Your Token:");
ui.horizontal(|ui| {
ui.add_sized(
[width / 8.0, text_edit],
TextEdit::singleline(&mut self.token),
)
.on_hover_text_at_pointer(XVB_HELP);
ui.add(Label::new(RichText::new(text_check).color(color)))
});
});
// need to warn the user if no address is set in p2pool tab
}
}

View file

@ -1,5 +1,6 @@
use anyhow::{bail, Result};
use hyper::StatusCode;
use hyper_tls::HttpsConnector;
use super::*;
use crate::{components::node::RemoteNode, disk::status::*};
@ -329,8 +330,8 @@ impl Default for P2pool {
impl Xvb {
pub async fn is_token_exist(address: String, token: String) -> Result<()> {
let client: hyper::Client<hyper::client::HttpConnector> =
hyper::Client::builder().build(hyper::client::HttpConnector::new());
let https = HttpsConnector::new();
let client = hyper::Client::builder().build(https);
if let Ok(request) = hyper::Request::builder()
.method("GET")
.uri(format!(
@ -339,16 +340,17 @@ impl Xvb {
))
.body(hyper::Body::empty())
{
if let Ok(resp) = client.request(request).await {
match resp.status() {
match client.request(request).await {
Ok(resp) => match resp.status() {
StatusCode::OK => Ok(()),
StatusCode::UNPROCESSABLE_ENTITY => {
bail!("the token is invalid for this xmr address.")
}
_ => bail!("The status of the response is not expected"),
},
Err(err) => {
bail!("error from response: {}", err)
}
} else {
bail!("error from response")
}
} else {
bail!("request could not be build")

View file

@ -412,6 +412,7 @@ impl Helper {
let lock = lock!(helper);
let p2pool = Arc::clone(&lock.p2pool);
let xmrig = Arc::clone(&lock.xmrig);
let xvb = Arc::clone(&lock.xvb);
let pub_sys = Arc::clone(&lock.pub_sys);
let gui_api_p2pool = Arc::clone(&lock.gui_api_p2pool);
let gui_api_xmrig = Arc::clone(&lock.gui_api_xmrig);
@ -438,25 +439,27 @@ impl Helper {
// 2. Lock... EVERYTHING!
let mut lock = lock!(helper);
debug!("Helper | Locking (1/10) ... [helper]");
debug!("Helper | Locking (1/11) ... [helper]");
let p2pool = lock!(p2pool);
debug!("Helper | Locking (2/10) ... [p2pool]");
debug!("Helper | Locking (2/11) ... [p2pool]");
let xmrig = lock!(xmrig);
debug!("Helper | Locking (3/10) ... [xmrig]");
debug!("Helper | Locking (3/11) ... [xmrig]");
let xvb = lock!(xvb);
debug!("Helper | Locking (4/11) ... [xvb]");
let mut lock_pub_sys = lock!(pub_sys);
debug!("Helper | Locking (4/10) ... [pub_sys]");
debug!("Helper | Locking (5/11) ... [pub_sys]");
let mut gui_api_p2pool = lock!(gui_api_p2pool);
debug!("Helper | Locking (5/10) ... [gui_api_p2pool]");
debug!("Helper | Locking (6/11) ... [gui_api_p2pool]");
let mut gui_api_xmrig = lock!(gui_api_xmrig);
debug!("Helper | Locking (6/10) ... [gui_api_xmrig]");
debug!("Helper | Locking (7/11) ... [gui_api_xmrig]");
let mut gui_api_xvb = lock!(gui_api_xvb);
debug!("Helper | Locking (7/10) ... [gui_api_xvb]");
debug!("Helper | Locking (8/11) ... [gui_api_xvb]");
let mut pub_api_p2pool = lock!(pub_api_p2pool);
debug!("Helper | Locking (8/10) ... [pub_api_p2pool]");
debug!("Helper | Locking (9/11) ... [pub_api_p2pool]");
let mut pub_api_xmrig = lock!(pub_api_xmrig);
debug!("Helper | Locking (9/10) ... [pub_api_xmrig]");
debug!("Helper | Locking (10/11) ... [pub_api_xmrig]");
let mut pub_api_xvb = lock!(pub_api_xvb);
debug!("Helper | Locking (10/10) ... [pub_api_xvb]");
debug!("Helper | Locking (11/11) ... [pub_api_xvb]");
// Calculate Gupax's uptime always.
lock.uptime = HumanTime::into_human(lock.instant.elapsed());
// If [P2Pool] is alive...
@ -473,9 +476,13 @@ impl Helper {
} else {
debug!("Helper | XMRig is dead! Skipping...");
}
// XvB API is considered always available
debug!("Helper | XvB is alive! Running [combine_gui_pub_api()]");
PubXvbApi::combine_gui_pub_api(&mut gui_api_xvb, &mut pub_api_xvb);
// If [XvB] is alive...
if xvb.is_alive() {
debug!("Helper | XvB is alive! Running [combine_gui_pub_api()]");
PubXvbApi::combine_gui_pub_api(&mut gui_api_xvb, &mut pub_api_xvb);
} else {
debug!("Helper | XvB is dead! Skipping...");
}
// 2. Selectively refresh [sysinfo] for only what we need (better performance).
sysinfo.refresh_cpu_specifics(sysinfo_cpu);
@ -495,25 +502,27 @@ impl Helper {
// 3. Drop... (almost) EVERYTHING... IN REVERSE!
drop(lock_pub_sys);
debug!("Helper | Unlocking (1/10) ... [pub_sys]");
debug!("Helper | Unlocking (1/11) ... [pub_sys]");
drop(xvb);
debug!("Helper | Unlocking (2/11) ... [xvb]");
drop(xmrig);
debug!("Helper | Unlocking (2/10) ... [xmrig]");
debug!("Helper | Unlocking (3/11) ... [xmrig]");
drop(p2pool);
debug!("Helper | Unlocking (3/10) ... [p2pool]");
debug!("Helper | Unlocking (4/11) ... [p2pool]");
drop(pub_api_xvb);
debug!("Helper | Unlocking (4/10) ... [pub_api_xvb]");
debug!("Helper | Unlocking (5/11) ... [pub_api_xvb]");
drop(pub_api_xmrig);
debug!("Helper | Unlocking (5/10) ... [pub_api_xmrig]");
debug!("Helper | Unlocking (6/11) ... [pub_api_xmrig]");
drop(pub_api_p2pool);
debug!("Helper | Unlocking (6/10) ... [pub_api_p2pool]");
debug!("Helper | Unlocking (7/11) ... [pub_api_p2pool]");
drop(gui_api_xvb);
debug!("Helper | Unlocking (7/10) ... [gui_api_xvb]");
debug!("Helper | Unlocking (8/11) ... [gui_api_xvb]");
drop(gui_api_xmrig);
debug!("Helper | Unlocking (8/10) ... [gui_api_xmrig]");
debug!("Helper | Unlocking (9/11) ... [gui_api_xmrig]");
drop(gui_api_p2pool);
debug!("Helper | Unlocking (9/10) ... [gui_api_p2pool]");
debug!("Helper | Unlocking (10/11) ... [gui_api_p2pool]");
drop(lock);
debug!("Helper | Unlocking (10/10) ... [helper]");
debug!("Helper | Unlocking (11/11) ... [helper]");
// 4. Calculate if we should sleep or not.
// If we should sleep, how long?

View file

@ -26,8 +26,13 @@ impl Helper {
// Just sets some signals for the watchdog thread to pick up on.
pub fn stop_xvb(helper: &Arc<Mutex<Self>>) {
info!("XvB | Attempting to stop...");
lock2!(helper, p2pool).signal = ProcessSignal::Stop;
lock2!(helper, p2pool).state = ProcessState::Middle;
lock2!(helper, xvb).signal = ProcessSignal::Stop;
lock2!(helper, xvb).state = ProcessState::Middle;
// Reset stats
let gui_api = Arc::clone(&lock!(helper).gui_api_xvb);
let pub_api = Arc::clone(&lock!(helper).pub_api_xvb);
*lock!(pub_api) = PubXvbApi::new();
*lock!(gui_api) = PubXvbApi::new();
}
pub fn restart_xvb(
helper: &Arc<Mutex<Self>>,
@ -35,8 +40,8 @@ impl Helper {
state_p2pool: &crate::disk::state::P2pool,
) {
info!("XvB | Attempting to restart...");
lock2!(helper, p2pool).signal = ProcessSignal::Restart;
lock2!(helper, p2pool).state = ProcessState::Middle;
lock2!(helper, xvb).signal = ProcessSignal::Restart;
lock2!(helper, xvb).state = ProcessState::Middle;
let helper = helper.clone();
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
@ -66,29 +71,39 @@ impl Helper {
let process = Arc::clone(&lock!(helper).xvb);
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
// two first verifications should be done before starting the process and giving the possibility to start it.
// verify if address is inserted
// if state_p2pool.address.is_empty() {
// warn!("Xvb | Start ... Failed because payout address is not inserted in P2pool tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// verify if token exist
// if state_xvb.token.is_empty() {
// warn!("Xvb | Start ... Failed because valid token is not inserted in XvB tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// 2. Set process state
debug!("XvB | Setting process state...");
{
let mut lock = lock!(process);
lock.state = ProcessState::Middle;
lock.signal = ProcessSignal::None;
lock.start = Instant::now();
}
// verify if token and address are existent on XvB server
let rt = tokio::runtime::Runtime::new().unwrap();
if !rt.block_on(async move {
Xvb::is_token_exist(state_p2pool.address, state_xvb.token)
.await
.is_ok()
}) {
warn!("Xvb | Start ... Failed because token and associated address are not existent on XvB server");
lock2!(helper, xvb).state = ProcessState::Failed;
return;
let resp: anyhow::Result<()> = rt.block_on(async move {
Xvb::is_token_exist(state_p2pool.address, state_xvb.token).await?;
Ok(())
});
match resp {
Ok(_) => {
let mut lock = lock!(process);
lock.state = ProcessState::Alive;
}
Err(err) => {
// send to console: token non existent for address on XvB server
warn!("Xvb | Start ... Failed because token and associated address are not existent on XvB server: {}", err);
// output the error to console
if let Err(e) = writeln!(
lock!(gui_api).output,
"Failure to retrieve private stats from XvB server.\nError: {}",
err
) {
error!("XvB Watchdog | GUI status write failed: {}", e);
}
lock2!(helper, xvb).state = ProcessState::NotMining;
}
}
thread::spawn(move || {
@ -104,49 +119,67 @@ impl Helper {
) {
info!("XvB started");
// 2. Set process state
debug!("XvB | Setting process state...");
{
let mut lock = lock!(process);
lock.state = ProcessState::Middle;
lock.signal = ProcessSignal::None;
lock.start = Instant::now();
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb started\n{}\n\n",
HORI_CONSOLE,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI status write failed: {}", e);
}
// Reset stats before loop
*lock!(pub_api) = PubXvbApi::new();
*lock!(gui_api) = PubXvbApi::new();
let start = lock!(process).start;
info!("XvB | Entering watchdog mode... woof!");
loop {
debug!("XvB Watchdog | ----------- Start of loop -----------");
// Set timer
let now = Instant::now();
// check signal
debug!("XvB | check signal");
if signal_interrupt(process.clone(), start, gui_api.clone()) {
break;
}
debug!("XvB Watchdog | ----------- Start of loop -----------");
// Send an HTTP API request
debug!("XvB Watchdog | Attempting HTTP API request...");
match PubXvbApi::request_xvb_public_api(client.clone(), XVB_URL_PUBLIC_API).await {
Ok(new_data) => {
debug!("XvB Watchdog | HTTP API request OK");
let mut data = lock!(&pub_api);
*data = new_data;
}
Err(err) => {
warn!(
"XvB Watchdog | Could not send HTTP API request to: {}\n:{}",
XVB_URL_PUBLIC_API, err
);
// Send an HTTP API request only if one minute is passed since the last.
// if since is 0, send request because it's the first time.
let since = lock!(gui_api).tick;
if since >= 60 || since == 0 {
// *lock!(pub_api) = PubXvbApi::new();
// *lock!(gui_api) = PubXvbApi::new();
debug!("XvB Watchdog | Attempting HTTP API request...");
match PubXvbApi::request_xvb_public_api(client.clone(), XVB_URL_PUBLIC_API).await {
Ok(new_data) => {
debug!("XvB Watchdog | HTTP API request OK");
*lock!(&pub_api) = new_data;
lock!(gui_api).tick += 0;
}
Err(err) => {
warn!(
"XvB Watchdog | Could not send HTTP API request to: {}\n:{}",
XVB_URL_PUBLIC_API, err
);
// output the error to console
if let Err(e) = writeln!(
lock!(gui_api).output,
"Failure to retrieve public stats from {}",
XVB_URL_PUBLIC_API
) {
error!("XvB Watchdog | GUI status write failed: {}", e);
}
lock!(process).state = ProcessState::Failed;
break;
}
}
}
// XvB Status do not need to be refreshed like others because combine_with_gui do not refresh if no data is changed.
let elapsed = now.elapsed().as_secs();
if elapsed < 59 {
let sleep = 60 - elapsed;
lock!(gui_api).tick += 1;
// Reset stats before loop
// Sleep (only if 900ms hasn't passed)
let elapsed = now.elapsed().as_millis();
// Since logic goes off if less than 1000, casting should be safe
if elapsed < 900 {
let sleep = (900 - elapsed) as u64;
debug!("XvB Watchdog | END OF LOOP - Sleeping for [{}]s...", sleep);
std::thread::sleep(std::time::Duration::from_secs(sleep))
std::thread::sleep(std::time::Duration::from_millis(sleep))
} else {
debug!("XMRig Watchdog | END OF LOOP - Not sleeping!");
}
@ -161,6 +194,8 @@ pub struct PubXvbApi {
pub output: String,
#[serde(skip)]
pub uptime: HumanTime,
#[serde(skip)]
pub tick: u8,
pub time_remain: u32, // remaining time of round in minutes
pub bonus_hr: f64,
pub donate_hr: f64, // donated hr from all donors
@ -205,11 +240,22 @@ impl PubXvbApi {
pub fn new() -> Self {
Self::default()
}
// The issue with just doing [gui_api = pub_api] is that values get overwritten.
// This doesn't matter for any of the values EXCEPT for the output, so we must
// manually append it instead of overwriting.
// This is used in the "helper" thread.
pub(super) fn combine_gui_pub_api(gui_api: &mut Self, pub_api: &mut Self) {
// update only if there is data, if no new data, pub_api fields are on default value.
if !pub_api.reward_yearly.is_empty() {
*gui_api = std::mem::take(pub_api)
let mut output = std::mem::take(&mut gui_api.output);
let buf = std::mem::take(&mut pub_api.output);
if !buf.is_empty() {
output.push_str(&buf);
}
let tick = std::mem::take(&mut gui_api.tick);
*gui_api = Self {
output,
tick,
..pub_api.clone()
};
}
#[inline]
// Send an HTTP request to XvB's API, serialize it into [Self] and return it
@ -258,23 +304,14 @@ fn signal_interrupt(
}
debug!("XvB Watchdog | Stop SIGNAL done, breaking");
lock!(process).signal = ProcessSignal::None;
lock!(process).state = ProcessState::Dead;
return true;
// Check RESTART
} else if lock!(process).signal == ProcessSignal::Restart {
debug!("XvB Watchdog | Restart SIGNAL caught");
let uptime = HumanTime::into_human(start.elapsed());
info!("XvB Watchdog | Stopped ... Uptime was: [{}]", uptime);
// insert the signal into output of XvB
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb stopped | Uptime: [{}] | \n{}\n\n\n\n",
HORI_CONSOLE,
uptime,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI Uptime/Exit status write failed: {}", e);
}
// no output to console because service will be started with fresh output.
debug!("XvB Watchdog | Restart SIGNAL done, breaking");
lock!(process).state = ProcessState::Waiting;
return true;

View file

@ -107,6 +107,7 @@ pub const XVB_DEAD: &str = "XvB process is offline";
pub const XVB_FAILED: &str = "XvB process is misconfigured or the XvB node is offline";
pub const XVB_MIDDLE: &str = "XvB is in the middle of (re)starting/stopping";
pub const XVB_NOT_CONFIGURED: &str = "You need to insert an existent token before starting XvB";
pub const XVB_PUBLIC_ONLY: &str = "XvB process is started only to get public stats";
// This is the typical space added when using
// [ui.separator()] or [ui.group()]
@ -409,6 +410,7 @@ pub const XMRIG_PATH_EMPTY: &str = "XMRig PATH is empty! To fix: goto the [G
pub const XVB_HELP: &str = "You need to register an account by clicking on the link above to get your token with the same p2pool XMR address you use for payment.";
pub const XVB_URL: &str = "https://xmrvsbeast.com";
pub const XVB_URL_PUBLIC_API: &str = "https://xmrvsbeast.com/p2pool/stats";
pub const XVB_TOKEN_LEN: usize = 9;
// CLI argument messages
pub const ARG_HELP: &str = r#"USAGE: ./gupax [--flag]