cat_gateway/
cli.rs

1//! CLI interpreter for the service
2use std::{io::Write, path::PathBuf};
3
4use clap::Parser;
5use tracing::{error, info};
6
7use crate::{
8    cardano::start_followers,
9    db::{self, index::session::CassandraSession},
10    service::{
11        self, started,
12        utilities::health::{is_live, live_counter_reset},
13    },
14    settings::{ServiceSettings, Settings},
15};
16
17#[derive(Parser)]
18#[clap(rename_all = "kebab-case")]
19/// Simple service CLI options
20pub(crate) enum Cli {
21    /// Run the service
22    Run(ServiceSettings),
23    /// Build API docs of the service in the JSON format
24    Docs {
25        /// The output path to the generated docs file, if omitted prints to stdout.
26        output: Option<PathBuf>,
27    },
28}
29
30impl Cli {
31    /// Execute the specified operation.
32    ///
33    /// This method is asynchronous and returns a `Result` indicating whether the
34    /// operation was successful or if an error occurred.
35    ///
36    /// # Errors
37    ///
38    /// This method can return an error if:
39    ///
40    /// - Failed to initialize the logger with the specified log level.
41    /// - Failed to create a new `State` with the provided database URL.
42    /// - Failed to run the service on the specified address.
43    pub(crate) async fn exec(self) -> anyhow::Result<()> {
44        match self {
45            Self::Run(settings) => {
46                Settings::init(settings)?;
47
48                let mut tasks = Vec::new();
49
50                info!("Catalyst Gateway - Starting");
51
52                // Start the DB's
53                CassandraSession::init();
54                db::event::establish_connection();
55
56                // Start the chain indexing follower.
57                start_followers().await?;
58
59                let handle = tokio::spawn(async move {
60                    match service::run().await {
61                        Ok(()) => info!("Endpoints started ok"),
62                        Err(err) => {
63                            error!("Error starting endpoints {err}");
64                        },
65                    }
66                });
67                tasks.push(handle);
68
69                let handle = tokio::spawn(async move {
70                    while is_live() {
71                        tokio::time::sleep(Settings::service_live_timeout_interval()).await;
72                        live_counter_reset();
73                    }
74                });
75                tasks.push(handle);
76
77                started();
78
79                for task in tasks {
80                    task.await?;
81                }
82
83                info!("Catalyst Gateway - Shut Down");
84            },
85            Self::Docs { output } => {
86                let docs = service::get_app_docs();
87                match output {
88                    Some(path) => {
89                        let mut docs_file = std::fs::File::create(path)?;
90                        docs_file.write_all(docs.as_bytes())?;
91                    },
92                    None => println!("{docs}"),
93                }
94            },
95        }
96
97        Ok(())
98    }
99}