mina_producer_dashboard/node/
watchdog.rs

1use tokio::{sync::mpsc::UnboundedSender, task::JoinHandle, time::Duration};
2
3use crate::{evaluator::EpochInit, storage::db_sled::Database, NodeStatus};
4
5use super::{daemon_status::SyncStatus, Node};
6
7// TODO(adonagy): move to struct
8pub fn spawn_watchdog(
9    node: Node,
10    status: NodeStatus,
11    db: Database,
12    sender: UnboundedSender<EpochInit>,
13    producer_pk: String,
14) -> JoinHandle<()> {
15    tokio::spawn(async move { watch(node, status, db, sender, producer_pk).await })
16}
17
18async fn watch(
19    node: Node,
20    status: NodeStatus,
21    db: Database,
22    sender: UnboundedSender<EpochInit>,
23    _producer_pk: String,
24) {
25    // TODO(adonagy): From config
26    let mut interval = tokio::time::interval(Duration::from_secs(5));
27
28    // TODO(adonagy): do not ignore this error
29    if node.wait_for_graphql().await.is_err() {
30        println!("[dbg] Error: returning");
31        return;
32    }
33
34    let genesis_timestamp = node.get_genesis_timestmap().await.unwrap();
35
36    {
37        let mut node_status = status.write().await;
38        node_status.genesis_timestamp = genesis_timestamp;
39    }
40
41    loop {
42        interval.tick().await;
43
44        println!("[node-watchdog] Tick");
45
46        let sync_status = node.sync_status().await;
47
48        if matches!(sync_status, SyncStatus::SYNCED) {
49            // TODO(adonagy): Probably won't need 2 calls
50            let best_tip = node.get_best_tip().await.unwrap();
51            let best_chain = node.get_best_chain().await.unwrap();
52            {
53                let mut status: tokio::sync::RwLockWriteGuard<'_, super::NodeData> =
54                    status.write().await;
55                status.best_tip = Some(best_tip.clone());
56                status.best_chain.clone_from(&best_chain);
57                status.sync_status = sync_status.clone()
58            }
59            let current_epoch: u32 = best_tip.consensus_state().epoch.parse().unwrap();
60
61            if !db.has_ledger(&current_epoch).unwrap() {
62                println!("Dumping staking ledger for epoch {current_epoch}");
63                let ledger = Node::get_staking_ledger(current_epoch);
64                let seed = best_tip.consensus_state().staking_epoch_data.seed.clone();
65                // TODO(adonagy): handle error
66                let _ = db.store_ledger(current_epoch, &ledger);
67                let _ = db.store_seed(current_epoch, seed.clone());
68
69                let mut status = status.write().await;
70
71                status.dumped_ledgers.insert(current_epoch);
72
73                let epoch_init = EpochInit::new(
74                    current_epoch,
75                    ledger,
76                    seed,
77                    best_tip.epoch_bounds().0,
78                    genesis_timestamp,
79                );
80                // TODO(adonagy): handle error
81                let _ = sender.send(epoch_init);
82            }
83        } else {
84            println!("Node not synced");
85        }
86    }
87}