use std::process::ExitCode;
use clap::{ArgMatches, Command, FromArgMatches, Subcommand};
use cerulion_cli_engine::message_text::VerbError;
use cerulion_cli_engine::service_cmd;
use super::nested::topic_message::{seconds, verb_exit_code};
use super::VerbFamily;
use crate::cli::VerbLogClass;
use crate::network_switch::{self, NetworkRefusal, SwitchEnv};
#[derive(Subcommand)]
enum ServiceCmd {
Service {
#[command(subcommand)]
action: ServiceAction,
},
}
#[derive(Subcommand)]
enum ServiceAction {
Call {
#[arg(long, value_name = "NAME",
add = clap_complete::engine::ArgValueCandidates::new(crate::completion::robot_names))]
robot: Option<String>,
#[arg(long, value_name = "SECS",
default_value_t = service_cmd::DEFAULT_CALL_TIMEOUT.as_secs_f64())]
timeout: f64,
service: String,
#[arg(value_name = "TYPE")]
type_name: String,
#[arg(default_value = "{}")]
request: String,
},
}
pub(crate) struct Service;
impl VerbFamily for Service {
fn name(&self) -> &'static str {
"service"
}
fn listed_after(&self) -> Option<&'static str> {
Some("topic")
}
fn command(&self) -> Command {
super::derived_verb::<ServiceCmd>()
}
fn log_class(&self, _matches: &ArgMatches) -> VerbLogClass {
VerbLogClass::OneShot
}
fn network_refusal(&self, matches: &ArgMatches, env: &SwitchEnv) -> Option<NetworkRefusal> {
match ServiceAction::from_arg_matches(matches).ok()? {
ServiceAction::Call { robot, .. } => network_switch::robot_refusal(
robot.as_deref(),
cerulion_cli_engine::robot_act::SERVICE_CALL_VERB,
env,
),
}
}
fn needs_identity(&self, _matches: &ArgMatches) -> bool {
true
}
fn run(&self, matches: &ArgMatches) -> ExitCode {
let action = ServiceAction::from_arg_matches(matches).unwrap_or_else(|e| e.exit());
verb_exit_code(run(action))
}
}
fn run(action: ServiceAction) -> Result<String, VerbError> {
match action {
ServiceAction::Call {
robot,
timeout,
service,
type_name,
request,
} => {
let ws = crate::discover_optional_workspace()?;
let schemas_dir = ws.as_ref().map(|w| w.schemas_dir.as_path());
let running = crate::setup_ctrlc_handler()?;
let req = service_cmd::CallRequest {
service: &service,
type_name: &type_name,
request: &request,
timeout: seconds("--timeout", timeout)?,
};
match robot {
Some(robot) => cerulion_cli_engine::robot_act::robot_service_call(&robot, &req),
None => service_cmd::service_call(&req, schemas_dir, &running),
}
}
}
}