use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use async_trait::async_trait;
use crate::error::WalletError;
use crate::monitor::helpers::now_msecs;
use crate::monitor::task_trait::WalletMonitorTask;
use crate::monitor::ONE_DAY;
use crate::services::traits::WalletServices;
use crate::status::ProvenTxReqStatus;
use crate::storage::find_args::{FindProvenTxReqsArgs, Paged, ProvenTxReqPartial};
use crate::storage::manager::WalletStorageManager;
use crate::types::Chain;
pub struct TaskCheckNoSends {
storage: Arc<WalletStorageManager>,
services: Arc<dyn WalletServices>,
chain: Chain,
trigger_msecs: u64,
last_run_msecs: u64,
unproven_attempts_limit: u32,
pub check_now: bool,
last_new_header_height: Arc<AtomicU32>,
}
impl TaskCheckNoSends {
pub fn new(
storage: Arc<WalletStorageManager>,
services: Arc<dyn WalletServices>,
chain: Chain,
unproven_attempts_limit: u32,
last_new_header_height: Arc<AtomicU32>,
) -> Self {
Self {
storage,
services,
chain,
trigger_msecs: ONE_DAY,
last_run_msecs: 0,
unproven_attempts_limit,
check_now: false,
last_new_header_height,
}
}
pub fn with_trigger_msecs(mut self, msecs: u64) -> Self {
self.trigger_msecs = msecs;
self
}
}
#[async_trait]
impl WalletMonitorTask for TaskCheckNoSends {
fn storage_manager(&self) -> Option<&WalletStorageManager> {
Some(&self.storage)
}
fn name(&self) -> &str {
"CheckNoSends"
}
fn trigger(&mut self, now_msecs: u64) -> bool {
self.check_now
|| (self.trigger_msecs > 0 && now_msecs > self.last_run_msecs + self.trigger_msecs)
}
async fn run_task(&mut self) -> Result<String, WalletError> {
self.last_run_msecs = now_msecs();
let counts_as_attempt = self.check_now;
self.check_now = false;
let mut log = String::new();
let raw_height = self.last_new_header_height.load(Ordering::SeqCst);
let max_acceptable_height = if raw_height == u32::MAX {
return Ok(log);
} else {
Some(raw_height)
};
let limit = 100i64;
let mut offset = 0i64;
loop {
let reqs = self
.storage
.find_proven_tx_reqs(&FindProvenTxReqsArgs {
partial: ProvenTxReqPartial::default(),
since: None,
paged: Some(Paged { limit, offset }),
statuses: Some(vec![ProvenTxReqStatus::Nosend]),
})
.await?;
if reqs.is_empty() {
break;
}
log.push_str(&format!("{} reqs with status 'nosend'\n", reqs.len()));
let r = crate::monitor::helpers::get_proofs(
&self.storage,
&*self.services,
&reqs,
&self.chain,
self.unproven_attempts_limit,
counts_as_attempt,
max_acceptable_height,
)
.await?;
log.push_str(&r.log);
log.push('\n');
if (reqs.len() as i64) < limit {
break;
}
offset += limit;
}
Ok(log)
}
}
#[cfg(test)]
mod tests {
use crate::monitor::ONE_DAY;
#[test]
fn test_check_no_sends_defaults() {
assert_eq!(ONE_DAY, 86_400_000);
}
#[test]
fn test_name() {
assert_eq!("CheckNoSends", "CheckNoSends");
}
}