mod commands;
mod logging;
use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, Subcommand};
use crate::commands::{
aggregate::AggregateCommands,
config::ConfigArgs,
plugin::{PluginCommands, PluginWorkerArgs},
queue::QueueArgs,
remote::RemoteCommands,
schema::SchemaCommands,
start::{DestroyArgs, StartArgs},
system::{BackupArgs, RestoreArgs},
token::TokenCommands,
upgrade::UpgradeArgs,
};
#[derive(Parser)]
#[command(author, version, about = "EventDBX server CLI")]
struct Cli {
#[arg(long)]
config: Option<PathBuf>,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Start(StartArgs),
Stop,
Status,
Restart(StartArgs),
Destroy(DestroyArgs),
Config(ConfigArgs),
Token {
#[command(subcommand)]
command: TokenCommands,
},
Schema {
#[command(subcommand)]
command: SchemaCommands,
},
Plugin {
#[command(subcommand)]
command: PluginCommands,
},
Queue(QueueArgs),
Aggregate {
#[command(subcommand)]
command: AggregateCommands,
},
Push(commands::remote::RemotePushArgs),
Pull(commands::remote::RemotePullArgs),
Upgrade(UpgradeArgs),
Remote {
#[command(subcommand)]
command: RemoteCommands,
},
Backup(BackupArgs),
Restore(RestoreArgs),
#[command(name = "__internal:server", hide = true)]
InternalServer,
#[command(name = "__internal:plugin-worker", hide = true)]
InternalPluginWorker(PluginWorkerArgs),
#[command(external_subcommand)]
External(Vec<String>),
}
#[tokio::main]
async fn main() -> Result<()> {
logging::init()?;
let Cli { config, command } = Cli::parse();
if !matches!(&command, Commands::Upgrade(_)) {
if let Err(err) = commands::upgrade::maybe_print_upgrade_notice().await {
tracing::debug!("upgrade notice check failed: {err:?}");
}
}
match command {
Commands::Start(args) => commands::start::execute(config, args).await?,
Commands::Stop => commands::start::stop(config)?,
Commands::Status => commands::start::status(config)?,
Commands::Restart(args) => restart(config, args).await?,
Commands::Destroy(args) => commands::start::destroy(config, args)?,
Commands::Config(args) => commands::config::execute(config, args)?,
Commands::Token { command } => commands::token::execute(config, command)?,
Commands::Schema { command } => commands::schema::execute(config, command)?,
Commands::Plugin { command } => commands::plugin::execute(config, command)?,
Commands::Queue(args) => commands::queue::execute(config, args)?,
Commands::Aggregate { command } => commands::aggregate::execute(config, command)?,
Commands::Push(args) => commands::remote::push(config, args).await?,
Commands::Pull(args) => commands::remote::pull(config, args).await?,
Commands::Upgrade(args) => commands::upgrade::execute(args).await?,
Commands::Remote { command } => commands::remote::execute(config, command).await?,
Commands::Backup(args) => commands::system::backup(config, args)?,
Commands::Restore(args) => commands::system::restore(config, args)?,
Commands::InternalServer => commands::start::run_internal(config).await?,
Commands::InternalPluginWorker(args) => {
commands::plugin::run_plugin_worker(config, args).await?
}
Commands::External(argv) => {
if !commands::upgrade::try_handle_shortcut(&argv).await? {
if let Some(name) = argv.first() {
anyhow::bail!("unknown command '{}'", name);
} else {
anyhow::bail!("unknown command");
}
}
}
}
Ok(())
}
async fn restart(config: Option<PathBuf>, args: StartArgs) -> Result<()> {
if let Err(err) = commands::start::stop(config.clone()) {
tracing::warn!("failed to stop EventDBX server before restart: {err}");
}
commands::start::execute(config, args).await
}