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

This commit is contained in:
aggstam
2024-01-11 17:50:03 +02:00
parent a27725b58f
commit 09137d4633
3 changed files with 38 additions and 6 deletions

View File

@@ -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())

View File

@@ -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);

View File

@@ -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)
}