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}