devimint/
recurringdv2.rs

1use std::ops::ControlFlow;
2
3use anyhow::Result;
4use fedimint_core::task::sleep;
5use fedimint_core::util::SafeUrl;
6use reqwest::get;
7use tracing::info;
8
9use crate::cmd;
10use crate::util::{ProcessHandle, ProcessManager, poll};
11
12#[derive(Clone)]
13pub struct Recurringdv2 {
14    pub(crate) process: ProcessHandle,
15    pub addr: String,
16    pub api_url: SafeUrl,
17}
18
19impl Recurringdv2 {
20    pub async fn new(process_mgr: &ProcessManager) -> Result<Self> {
21        let port = process_mgr.globals.FM_PORT_RECURRINGDV2;
22        let bind_address = format!("127.0.0.1:{port}");
23        let api_url = SafeUrl::parse(&format!("http://{bind_address}/")).expect("Valid URL");
24
25        let process = process_mgr
26            .spawn_daemon(
27                "recurringdv2",
28                cmd!("fedimint-recurringdv2", "--bind-api", bind_address.clone()),
29            )
30            .await?;
31
32        let recurringdv2 = Self {
33            process,
34            addr: bind_address,
35            api_url,
36        };
37
38        poll("waiting for recurringdv2 to be ready", || async {
39            match get(format!("http://{}", recurringdv2.addr)).await {
40                Ok(response) if response.status().is_success() => Ok(()),
41                _ => {
42                    sleep(tokio::time::Duration::from_millis(100)).await;
43                    Err(ControlFlow::Continue(anyhow::anyhow!(
44                        "recurringdv2 not ready yet"
45                    )))
46                }
47            }
48        })
49        .await?;
50
51        info!("Recurringdv2 started at {}", recurringdv2.addr);
52        Ok(recurringdv2)
53    }
54
55    pub async fn terminate(self) -> Result<()> {
56        self.process.terminate().await
57    }
58
59    pub fn api_url(&self) -> SafeUrl {
60        self.api_url.clone()
61    }
62}