Răsfoiți Sursa

script/research/minerd: handle new request trigger using smol channels

aggstam 2 ani în urmă
părinte
comite
09137d4633

+ 2 - 0
script/research/minerd/src/error.rs

@@ -28,6 +28,7 @@ pub enum RpcError {
     // Miner errors
     MiningFailed = -32201,
     HashingFailed = -32202,
+    StopFailed = -32203,
 }
 
 fn to_tuple(e: RpcError) -> (i32, String) {
@@ -38,6 +39,7 @@ fn to_tuple(e: RpcError) -> (i32, String) {
         // Miner errors
         RpcError::MiningFailed => "Mining block failed",
         RpcError::HashingFailed => "Hashing block failed",
+        RpcError::StopFailed => "Failed to stop previous request",
     };
 
     (e as i32, msg.to_string())

+ 11 - 4
script/research/minerd/src/main.rs

@@ -19,7 +19,12 @@
 use std::{collections::HashSet, sync::Arc};
 
 use log::{error, info};
-use smol::{channel::Receiver, lock::Mutex, stream::StreamExt, Executor};
+use smol::{
+    channel::{Receiver, Sender},
+    lock::Mutex,
+    stream::StreamExt,
+    Executor,
+};
 use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
 use url::Url;
 
@@ -68,6 +73,8 @@ struct Args {
 pub struct Minerd {
     /// PoW miner number of threads to use
     threads: usize,
+    // Sender to stop miner threads
+    sender: Sender<()>,
     // Receiver to stop miner threads
     stop_signal: Receiver<()>,
     /// JSON-RPC connection tracker
@@ -75,8 +82,8 @@ pub struct Minerd {
 }
 
 impl Minerd {
-    pub fn new(threads: usize, stop_signal: Receiver<()>) -> Self {
-        Self { threads, stop_signal, rpc_connections: Mutex::new(HashSet::new()) }
+    pub fn new(threads: usize, sender: Sender<()>, stop_signal: Receiver<()>) -> Self {
+        Self { threads, sender, stop_signal, rpc_connections: Mutex::new(HashSet::new()) }
     }
 }
 
@@ -84,7 +91,7 @@ async_daemonize!(realmain);
 async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
     info!(target: "minerd", "Starting DarkFi Mining Daemon...");
     let (sender, recvr) = smol::channel::bounded(1);
-    let minerd = Arc::new(Minerd::new(args.threads, recvr));
+    let minerd = Arc::new(Minerd::new(args.threads, sender.clone(), recvr));
 
     info!(target: "minerd", "Starting JSON-RPC server on {}", args.rpc_listen);
     let minerd_ = Arc::clone(&minerd);

+ 25 - 2
script/research/minerd/src/rpc.rs

@@ -29,7 +29,7 @@ use darkfi::{
         server::RequestHandler,
         util::JsonValue,
     },
-    system::StoppableTaskPtr,
+    system::{sleep, StoppableTaskPtr},
     util::encoding::base64,
     validator::pow::mine_block,
 };
@@ -88,13 +88,36 @@ impl Minerd {
             return server_error(RpcError::BlockParseError, id, None)
         };
 
+        // Check if another request is being processed
+        if self.stop_signal.receiver_count() > 1 {
+            info!(target: "minerd::rpc", "Another request is in progress, sending stop signal...");
+            // Send stop signal to other worker
+            if self.sender.send(()).await.is_err() {
+                error!(target: "minerd::rpc", "Failed to stop previous request");
+                return server_error(RpcError::StopFailed, id, None)
+            }
+
+            // Wait for other worker to terminate
+            info!(target: "minerd::rpc", "Waiting for request to terminate...");
+            while self.stop_signal.receiver_count() > 1 {
+                sleep(1).await;
+            }
+            info!(target: "minerd::rpc", "Previous request terminated!");
+
+            // Consume channel item so its empty again
+            if self.stop_signal.recv().await.is_err() {
+                error!(target: "minerd::rpc", "Failed to cleanup stop signal channel");
+                return server_error(RpcError::StopFailed, id, None)
+            }
+        }
+
         // Mine provided block
         let Ok(block_hash) = block.hash() else {
             error!(target: "minerd::rpc", "Failed to hash block");
             return server_error(RpcError::HashingFailed, id, None)
         };
         info!(target: "minerd::rpc", "Mining block {} for target: {}", block_hash, target);
-        if let Err(e) = mine_block(&target, &mut block, self.threads, &self.stop_signal) {
+        if let Err(e) = mine_block(&target, &mut block, self.threads, &self.stop_signal.clone()) {
             error!(target: "minerd::rpc", "Failed mining block {} with error: {}", block_hash, e);
             return server_error(RpcError::MiningFailed, id, None)
         }