Skip to main content

bsv_wallet_toolbox/monitor/tasks/
task_review_status.rs

1//! TaskReviewStatus -- reviews stale transaction statuses and logs corrections.
2//!
3//! Translated from wallet-toolbox/src/monitor/tasks/TaskReviewStatus.ts.
4
5use async_trait::async_trait;
6
7use crate::error::WalletError;
8use crate::monitor::helpers::now_msecs;
9use crate::monitor::task_trait::WalletMonitorTask;
10use crate::monitor::ONE_MINUTE;
11use crate::storage::manager::WalletStorageManager;
12
13/// Task that reviews stale transaction statuses and corrects them.
14///
15/// Looks for aged Transactions with provenTxId with status != 'completed',
16/// sets status to 'completed'. Also looks for reqs with 'invalid' status
17/// that have corresponding transactions with status other than 'failed'.
18pub struct TaskReviewStatus {
19    storage: WalletStorageManager,
20    trigger_msecs: u64,
21    last_run_msecs: u64,
22    /// How old a record must be before it is considered "aged" for review.
23    aged_limit_msecs: u64,
24}
25
26impl TaskReviewStatus {
27    /// Create a new status review task.
28    pub fn new(storage: WalletStorageManager) -> Self {
29        Self {
30            storage,
31            trigger_msecs: 15 * ONE_MINUTE,
32            last_run_msecs: 0,
33            aged_limit_msecs: 5 * ONE_MINUTE,
34        }
35    }
36
37    /// Set the trigger interval in milliseconds.
38    pub fn with_trigger_msecs(mut self, msecs: u64) -> Self {
39        self.trigger_msecs = msecs;
40        self
41    }
42
43    /// Set the aged limit threshold in milliseconds.
44    pub fn with_aged_limit_msecs(mut self, msecs: u64) -> Self {
45        self.aged_limit_msecs = msecs;
46        self
47    }
48}
49
50#[async_trait]
51impl WalletMonitorTask for TaskReviewStatus {
52    fn name(&self) -> &str {
53        "ReviewStatus"
54    }
55
56    fn trigger(&mut self, now_msecs: u64) -> bool {
57        self.trigger_msecs > 0 && now_msecs > self.last_run_msecs + self.trigger_msecs
58    }
59
60    async fn run_task(&mut self) -> Result<String, WalletError> {
61        self.last_run_msecs = now_msecs();
62        let now = chrono::Utc::now().naive_utc();
63        let aged_limit = now - chrono::Duration::milliseconds(self.aged_limit_msecs as i64);
64
65        use crate::storage::traits::reader_writer::StorageReaderWriter;
66        let result = self.storage.review_status(aged_limit).await?;
67        Ok(result)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use crate::monitor::ONE_MINUTE;
74
75    #[test]
76    fn test_review_status_defaults() {
77        // Verify default intervals match TS
78        assert_eq!(15 * ONE_MINUTE, 900_000); // 15 minutes
79        assert_eq!(5 * ONE_MINUTE, 300_000); // 5 minutes
80    }
81
82    #[test]
83    fn test_name() {
84        assert_eq!("ReviewStatus", "ReviewStatus");
85    }
86}