objectstore_server/
cli.rs1use std::fs::File;
7use std::path::PathBuf;
8use std::thread;
9use std::time::Duration;
10
11use anyhow::Result;
12use argh::FromArgs;
13
14use crate::config::Config;
15use crate::endpoints::health::SHUTDOWN_MARKER_PATH;
16use crate::{healthcheck, observability, web};
17
18#[derive(Debug, FromArgs)]
20struct Args {
21 #[argh(option, short = 'c')]
23 pub config: Option<PathBuf>,
24
25 #[argh(subcommand)]
26 pub command: Command,
27}
28
29#[derive(Debug, FromArgs)]
30#[argh(subcommand)]
31enum Command {
32 Run(RunCommand),
33 Healthcheck(HealthcheckCommand),
34 Version(VersionCommand),
35 Sleep(SleepCommand),
36 Down(DownCommand),
37}
38
39#[derive(Debug, FromArgs)]
41#[argh(subcommand, name = "run")]
42struct RunCommand {}
43
44#[derive(Debug, FromArgs)]
49#[argh(subcommand, name = "healthcheck")]
50struct HealthcheckCommand {}
51
52#[derive(Default, Debug, FromArgs)]
54#[argh(subcommand, name = "version")]
55struct VersionCommand {}
56
57#[derive(Debug, FromArgs)]
59#[argh(subcommand, name = "sleep")]
60struct SleepCommand {
61 #[argh(positional)]
62 seconds: u64,
63}
64
65#[derive(Debug, FromArgs)]
67#[argh(subcommand, name = "down")]
68struct DownCommand {
69 #[argh(positional)]
71 sleep_seconds: Option<u64>,
72}
73
74pub fn execute() -> Result<()> {
76 let args: Args = argh::from_env();
77
78 if let Command::Version(_) = args.command {
80 println!("{}", env!("OBJECTSTORE_RELEASE"));
81 return Ok(());
82 }
83
84 if let Command::Sleep(SleepCommand { seconds }) = args.command {
85 thread::sleep(Duration::from_secs(seconds));
86 return Ok(());
87 }
88
89 if let Command::Down(DownCommand { sleep_seconds }) = args.command {
90 File::create(SHUTDOWN_MARKER_PATH)?;
91 if let Some(seconds) = sleep_seconds {
92 thread::sleep(Duration::from_secs(seconds));
93 }
94 return Ok(());
95 }
96
97 let config = Config::load(args.config.as_deref())?;
98
99 rustls::crypto::ring::default_provider()
101 .install_default()
102 .map_err(|_| anyhow::anyhow!("Failed to install rustls crypto provider"))?;
103
104 let _sentry_guard = observability::init_sentry(&config);
106
107 let runtime = tokio::runtime::Builder::new_multi_thread()
108 .thread_name("main-rt")
109 .enable_all()
110 .worker_threads(config.runtime.worker_threads)
111 .build()?;
112 let _runtime_guard = runtime.enter();
113
114 observability::init_tracing(&config);
115 tracing::debug!(?config);
116
117 objectstore_metrics::init(&config.metrics)?;
118
119 runtime.block_on(async move {
120 match args.command {
121 Command::Run(RunCommand {}) => web::server(config).await,
122 Command::Healthcheck(HealthcheckCommand {}) => healthcheck::healthcheck(config).await,
123 Command::Version(VersionCommand {})
124 | Command::Sleep(SleepCommand { .. })
125 | Command::Down(DownCommand { .. }) => {
126 unreachable!()
127 }
128 }
129 })
130}