Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: make the command entry cleaner #3981

Merged
merged 5 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 35 additions & 74 deletions src/cmd/src/bin/greptime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@

#![doc = include_str!("../../../../README.md")]

use std::fmt;

use clap::{Parser, Subcommand};
use cmd::error::Result;
use cmd::options::{GlobalOptions, Options};
use cmd::{cli, datanode, frontend, log_versions, metasrv, standalone, start_app, App};
use cmd::options::GlobalOptions;
use cmd::{cli, datanode, frontend, log_versions, metasrv, standalone, App};
use common_version::{short_version, version};

#[derive(Parser)]
Expand Down Expand Up @@ -56,87 +54,50 @@ enum SubCommand {
Cli(cli::Command),
}

impl SubCommand {
async fn build(self, opts: Options) -> Result<Box<dyn App>> {
let app: Box<dyn App> = match (self, opts) {
(SubCommand::Datanode(cmd), Options::Datanode(dn_opts)) => {
let app = cmd.build(*dn_opts).await?;
Box::new(app) as _
}
(SubCommand::Frontend(cmd), Options::Frontend(fe_opts)) => {
let app = cmd.build(*fe_opts).await?;
Box::new(app) as _
}
(SubCommand::Metasrv(cmd), Options::Metasrv(meta_opts)) => {
let app = cmd.build(*meta_opts).await?;
Box::new(app) as _
}
(SubCommand::Standalone(cmd), Options::Standalone(opts)) => {
let app = cmd.build(*opts).await?;
Box::new(app) as _
}
(SubCommand::Cli(cmd), Options::Cli(_)) => {
let app = cmd.build().await?;
Box::new(app) as _
}

_ => unreachable!(),
};
Ok(app)
}

fn load_options(&self, global_options: &GlobalOptions) -> Result<Options> {
match self {
SubCommand::Datanode(cmd) => cmd.load_options(global_options),
SubCommand::Frontend(cmd) => cmd.load_options(global_options),
SubCommand::Metasrv(cmd) => cmd.load_options(global_options),
SubCommand::Standalone(cmd) => cmd.load_options(global_options),
SubCommand::Cli(cmd) => cmd.load_options(global_options),
}
}
}

impl fmt::Display for SubCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubCommand::Datanode(..) => write!(f, "greptime-datanode"),
SubCommand::Frontend(..) => write!(f, "greptime-frontend"),
SubCommand::Metasrv(..) => write!(f, "greptime-metasrv"),
SubCommand::Standalone(..) => write!(f, "greptime-standalone"),
SubCommand::Cli(_) => write!(f, "greptime-cli"),
}
}
}

#[cfg(not(windows))]
#[global_allocator]
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

#[tokio::main]
async fn main() -> Result<()> {
setup_human_panic();
log_versions(version!(), short_version!());
start(Command::parse()).await
}

async fn start(cli: Command) -> Result<()> {
let subcmd = cli.subcmd;

let app_name = subcmd.to_string();

let opts = subcmd.load_options(&cli.global_options)?;

let _guard = common_telemetry::init_global_logging(
&app_name,
opts.logging_options(),
&cli.global_options.tracing_options(),
opts.node_id(),
);

log_versions(version!(), short_version!());

let app = subcmd.build(opts).await?;

start_app(app).await
match cli.subcmd {
SubCommand::Datanode(cmd) => {
cmd.build(cmd.load_options(&cli.global_options)?)
.await?
.run()
.await
}
SubCommand::Frontend(cmd) => {
cmd.build(cmd.load_options(&cli.global_options)?)
.await?
.run()
.await
}
SubCommand::Metasrv(cmd) => {
cmd.build(cmd.load_options(&cli.global_options)?)
.await?
.run()
.await
}
SubCommand::Standalone(cmd) => {
cmd.build(cmd.load_options(&cli.global_options)?)
.await?
.run()
.await
}
SubCommand::Cli(cmd) => {
cmd.build(cmd.load_options(&cli.global_options)?)
.await?
.run()
.await
}
}
}

fn setup_human_panic() {
Expand Down
23 changes: 16 additions & 7 deletions src/cmd/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ mod upgrade;
use async_trait::async_trait;
use bench::BenchTableMetadataCommand;
use clap::Parser;
use common_telemetry::logging::LoggingOptions;
use common_telemetry::logging::{LoggingOptions, TracingOptions};
// pub use repl::Repl;
use upgrade::UpgradeCommand;

use self::export::ExportCommand;
use crate::error::Result;
use crate::options::{GlobalOptions, Options};
use crate::options::GlobalOptions;
use crate::App;

pub const APP_NAME: &str = "greptime-cli";

#[async_trait]
pub trait Tool: Send + Sync {
async fn do_work(&self) -> Result<()>;
Expand All @@ -57,7 +59,7 @@ impl Instance {
#[async_trait]
impl App for Instance {
fn name(&self) -> &str {
"greptime-cli"
APP_NAME
}

async fn start(&mut self) -> Result<()> {
Expand All @@ -80,11 +82,18 @@ pub struct Command {
}

impl Command {
pub async fn build(self) -> Result<Instance> {
pub async fn build(&self, opts: LoggingOptions) -> Result<Instance> {
let _guard = common_telemetry::init_global_logging(
APP_NAME,
&opts,
&TracingOptions::default(),
None,
);

self.cmd.build().await
}

pub fn load_options(&self, global_options: &GlobalOptions) -> Result<Options> {
pub fn load_options(&self, global_options: &GlobalOptions) -> Result<LoggingOptions> {
let mut logging_opts = LoggingOptions::default();

if let Some(dir) = &global_options.log_dir {
Expand All @@ -93,7 +102,7 @@ impl Command {

logging_opts.level.clone_from(&global_options.log_level);

Ok(Options::Cli(Box::new(logging_opts)))
Ok(logging_opts)
}
}

Expand All @@ -106,7 +115,7 @@ enum SubCommand {
}

impl SubCommand {
async fn build(self) -> Result<Instance> {
async fn build(&self) -> Result<Instance> {
match self {
// SubCommand::Attach(cmd) => cmd.build().await,
SubCommand::Upgrade(cmd) => cmd.build().await,
Expand Down
72 changes: 34 additions & 38 deletions src/cmd/src/datanode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ use snafu::{OptionExt, ResultExt};
use crate::error::{
LoadLayeredConfigSnafu, MissingConfigSnafu, Result, ShutdownDatanodeSnafu, StartDatanodeSnafu,
};
use crate::options::{GlobalOptions, Options};
use crate::options::GlobalOptions;
use crate::App;

pub const APP_NAME: &str = "greptime-datanode";

pub struct Instance {
datanode: Datanode,
}
Expand All @@ -56,7 +58,7 @@ impl Instance {
#[async_trait]
impl App for Instance {
fn name(&self) -> &str {
"greptime-datanode"
APP_NAME
}

async fn start(&mut self) -> Result<()> {
Expand All @@ -82,11 +84,11 @@ pub struct Command {
}

impl Command {
pub async fn build(self, opts: DatanodeOptions) -> Result<Instance> {
pub async fn build(&self, opts: DatanodeOptions) -> Result<Instance> {
self.subcmd.build(opts).await
}

pub fn load_options(&self, global_options: &GlobalOptions) -> Result<Options> {
pub fn load_options(&self, global_options: &GlobalOptions) -> Result<DatanodeOptions> {
self.subcmd.load_options(global_options)
}
}
Expand All @@ -97,13 +99,13 @@ enum SubCommand {
}

impl SubCommand {
async fn build(self, opts: DatanodeOptions) -> Result<Instance> {
async fn build(&self, opts: DatanodeOptions) -> Result<Instance> {
match self {
SubCommand::Start(cmd) => cmd.build(opts).await,
}
}

fn load_options(&self, global_options: &GlobalOptions) -> Result<Options> {
fn load_options(&self, global_options: &GlobalOptions) -> Result<DatanodeOptions> {
match self {
SubCommand::Start(cmd) => cmd.load_options(global_options),
}
Expand Down Expand Up @@ -135,17 +137,15 @@ struct StartCommand {
}

impl StartCommand {
fn load_options(&self, global_options: &GlobalOptions) -> Result<Options> {
Ok(Options::Datanode(Box::new(
self.merge_with_cli_options(
global_options,
DatanodeOptions::load_layered_options(
self.config_file.as_deref(),
self.env_prefix.as_ref(),
)
.context(LoadLayeredConfigSnafu)?,
)?,
)))
fn load_options(&self, global_options: &GlobalOptions) -> Result<DatanodeOptions> {
self.merge_with_cli_options(
global_options,
DatanodeOptions::load_layered_options(
self.config_file.as_deref(),
self.env_prefix.as_ref(),
)
.context(LoadLayeredConfigSnafu)?,
)
}

// The precedence order is: cli > config file > environment variables > default values.
Expand Down Expand Up @@ -226,7 +226,14 @@ impl StartCommand {
Ok(opts)
}

async fn build(self, mut opts: DatanodeOptions) -> Result<Instance> {
async fn build(&self, mut opts: DatanodeOptions) -> Result<Instance> {
let _guard = common_telemetry::init_global_logging(
APP_NAME,
&opts.logging,
&opts.tracing,
opts.node_id.map(|x| x.to_string()),
);

let plugins = plugins::setup_datanode_plugins(&mut opts)
.await
.context(StartDatanodeSnafu)?;
Expand Down Expand Up @@ -337,10 +344,7 @@ mod tests {
..Default::default()
};

let Options::Datanode(options) = cmd.load_options(&GlobalOptions::default()).unwrap()
else {
unreachable!()
};
let options = cmd.load_options(&GlobalOptions::default()).unwrap();

assert_eq!("127.0.0.1:3001".to_string(), options.rpc_addr);
assert_eq!(Some(42), options.node_id);
Expand Down Expand Up @@ -399,23 +403,19 @@ mod tests {

#[test]
fn test_try_from_cmd() {
if let Options::Datanode(opt) = StartCommand::default()
let opt = StartCommand::default()
.load_options(&GlobalOptions::default())
.unwrap()
{
assert_eq!(Mode::Standalone, opt.mode)
}
.unwrap();
assert_eq!(Mode::Standalone, opt.mode);

if let Options::Datanode(opt) = (StartCommand {
let opt = (StartCommand {
node_id: Some(42),
metasrv_addrs: Some(vec!["127.0.0.1:3002".to_string()]),
..Default::default()
})
.load_options(&GlobalOptions::default())
.unwrap()
{
assert_eq!(Mode::Distributed, opt.mode)
}
.unwrap();
assert_eq!(Mode::Distributed, opt.mode);

assert!((StartCommand {
metasrv_addrs: Some(vec!["127.0.0.1:3002".to_string()]),
Expand Down Expand Up @@ -447,7 +447,7 @@ mod tests {
})
.unwrap();

let logging_opt = options.logging_options();
let logging_opt = options.logging;
assert_eq!("/tmp/greptimedb/test/logs", logging_opt.dir);
assert_eq!("debug", logging_opt.level.as_ref().unwrap());
}
Expand Down Expand Up @@ -527,11 +527,7 @@ mod tests {
..Default::default()
};

let Options::Datanode(opts) =
command.load_options(&GlobalOptions::default()).unwrap()
else {
unreachable!()
};
let opts = command.load_options(&GlobalOptions::default()).unwrap();

// Should be read from env, env > default values.
let DatanodeWalConfig::RaftEngine(raft_engine_config) = opts.wal else {
Expand Down
Loading
Loading