From 4f9afdc827b8daa9b91898a415ee4ccbf1660b55 Mon Sep 17 00:00:00 2001
From: Cyrix126 <58007246+Cyrix126@users.noreply.github.com>
Date: Fri, 3 Jan 2025 20:50:54 +0100
Subject: [PATCH] feat: fast detection of offline Node

---
 src/helper/p2pool.rs   | 26 +++++++++++++++++++++-----
 src/helper/tests.rs    | 14 +-------------
 src/utils/constants.rs |  2 +-
 3 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/src/helper/p2pool.rs b/src/helper/p2pool.rs
index 3318d3a..326f3a2 100644
--- a/src/helper/p2pool.rs
+++ b/src/helper/p2pool.rs
@@ -659,12 +659,21 @@ impl Helper {
                 debug!("P2Pool Watchdog | Starting [update_from_output()]");
                 let mut process_lock = process.lock().unwrap();
                 let mut pub_api_lock = pub_api.lock().unwrap();
+
+                // if zmq fails were detected, we should increment the timer
+                if let Some(timer) = &mut pub_api_lock.fails_zmq_since {
+                    *timer += 1;
+                }
+                // after 5 seconds without being reset to 0, set to none.
+                if pub_api_lock.fails_zmq_since.is_some_and(|t| t == 5) {
+                    info!("P2Pool Watchdog | 5 seconds since a ZMQ failure was seen");
+                    pub_api_lock.fails_zmq_since = None;
+                }
                 PubP2poolApi::update_from_output(
                     &mut pub_api_lock,
                     &output_parse,
                     &output_pub,
                     start.elapsed(),
-                    &mut process_lock,
                 );
 
                 // Read [local] API
@@ -874,6 +883,7 @@ pub struct PubP2poolApi {
     pub sidechain_shares: u32,
     pub sidechain_ehr: f32,
     pub sidechain_height: u32,
+    pub fails_zmq_since: Option<u32>,
     // from local/p2p
     pub p2p_connected: u32,
     pub node_connected: bool,
@@ -933,6 +943,7 @@ impl PubP2poolApi {
             p2p_connected: 0,
             node_connected: false,
             prefer_local_node: true,
+            fails_zmq_since: None,
         }
     }
 
@@ -984,7 +995,6 @@ impl PubP2poolApi {
         output_parse: &Arc<Mutex<String>>,
         output_pub: &Arc<Mutex<String>>,
         elapsed: std::time::Duration,
-        process: &mut Process,
     ) {
         // 1. Take the process's current output buffer and combine it with Pub (if not empty)
         let mut output_pub = output_pub.lock().unwrap();
@@ -997,8 +1007,10 @@ impl PubP2poolApi {
         let mut output_parse = output_parse.lock().unwrap();
         let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
         // if the node is offline, p2pool can not function properly. Requires at least p2pool log level 1
-        if process.state == ProcessState::Alive && contains_zmq_failure(&output_parse) {
-            process.state = ProcessState::Syncing;
+        // if log level 0, it will take 2 minutes to detect that the node is offline.
+        if contains_zmq_failure(&output_parse) {
+            warn!("P2Pool Watchdog | a ZMQ failure was seen, check connection to Node");
+            public.fails_zmq_since = Some(0);
         }
 
         // 3. Throw away [output_parse]
@@ -1166,11 +1178,15 @@ impl PubP2poolApi {
             && self.node_connected
             && self.p2p_connected > 1
             && self.sidechain_height > 1000
+            && self.fails_zmq_since.is_none()
         {
             process.state = ProcessState::Alive;
         }
         if process.state == ProcessState::Alive
-            && (self.sidechain_height < 1000 || !self.node_connected || self.p2p_connected == 0)
+            && (self.sidechain_height < 1000
+                || !self.node_connected
+                || self.p2p_connected == 0
+                || self.fails_zmq_since.is_some())
         {
             process.state = ProcessState::Syncing;
         }
diff --git a/src/helper/tests.rs b/src/helper/tests.rs
index 7d66a5f..9f56e92 100644
--- a/src/helper/tests.rs
+++ b/src/helper/tests.rs
@@ -131,19 +131,8 @@ Uptime         = 0h 2m 4s
         )));
         let output_pub = Arc::new(Mutex::new(String::new()));
         let elapsed = std::time::Duration::from_secs(60);
-        let process = Arc::new(Mutex::new(Process::new(
-            ProcessName::P2pool,
-            "".to_string(),
-            PathBuf::new(),
-        )));
         let mut public = public.lock().unwrap();
-        PubP2poolApi::update_from_output(
-            &mut public,
-            &output_parse,
-            &output_pub,
-            elapsed,
-            &mut process.lock().unwrap(),
-        );
+        PubP2poolApi::update_from_output(&mut public, &output_parse, &output_pub, elapsed);
         println!("{:#?}", public);
         assert_eq!(public.payouts, 3);
         assert_eq!(public.payouts_hour, 180.0);
@@ -184,7 +173,6 @@ Uptime         = 0h 2m 4s
             &output_parse,
             &output_pub,
             elapsed,
-            &mut process.lock().unwrap(),
         );
         println!("{:#?}", process);
         assert!(process.lock().unwrap().state == ProcessState::Syncing); // still syncing
diff --git a/src/utils/constants.rs b/src/utils/constants.rs
index 31066c2..a2a5a3c 100644
--- a/src/utils/constants.rs
+++ b/src/utils/constants.rs
@@ -387,7 +387,7 @@ pub const P2POOL_MAIN: &str = "Use the P2Pool main-chain. This P2Pool finds bloc
 pub const P2POOL_MINI: &str = "Use the P2Pool mini-chain. This P2Pool finds blocks slower, but has a lower difficulty. Suitable for miners with less than 50kH/s";
 pub const P2POOL_OUT: &str = "How many out-bound peers to connect to? (you connecting to others)";
 pub const P2POOL_IN: &str = "How many in-bound peers to allow? (others connecting to you)";
-pub const P2POOL_LOG: &str = "Verbosity of the console log";
+pub const P2POOL_LOG: &str = "Verbosity of the console log.\nA verbosity level more than 0 is recommended to let the P2Pool process detect more rapidly errors with the Monero Node.\nIf the level is at 0, it can take up to 2 minutes to detect an error.";
 pub const P2POOL_AUTO_NODE: &str = "Automatically ping the remote Monero nodes at Gupaxx startup";
 pub const P2POOL_AUTO_SELECT: &str =
     "Automatically select the fastest remote Monero node after pinging";