use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, Subcommand, ValueHint};
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ValorApplicationConfig {
cluster: ValorClusterConfig,
master: ValorNodeConfig,
worker: ValorNodeConfig,
#[serde(default)]
runtime: ValorRuntimeTuning,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ValorClusterConfig {
pub cookie: String,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ValorNodeConfig {
port: u16,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ValorRuntimeTuning {
#[serde(default = "ValorRuntimeTuning::default_heartbeat_interval_ms")]
pub heartbeat_interval_ms: u64,
#[serde(default = "ValorRuntimeTuning::default_missed_before_unreachable")]
pub missed_before_unreachable: u32,
#[serde(default = "ValorRuntimeTuning::default_unreachable_after_secs")]
pub unreachable_after_secs: u64,
#[serde(default = "ValorRuntimeTuning::default_eviction_after_secs")]
pub eviction_after_secs: u64,
#[serde(default = "ValorRuntimeTuning::default_task_timeout_ms")]
pub task_default_timeout_ms: u64,
}
impl Default for ValorRuntimeTuning {
fn default() -> Self {
Self {
heartbeat_interval_ms: Self::default_heartbeat_interval_ms(),
missed_before_unreachable: Self::default_missed_before_unreachable(),
unreachable_after_secs: Self::default_unreachable_after_secs(),
eviction_after_secs: Self::default_eviction_after_secs(),
task_default_timeout_ms: Self::default_task_timeout_ms(),
}
}
}
impl ValorRuntimeTuning {
fn default_heartbeat_interval_ms() -> u64 {
5000
}
fn default_missed_before_unreachable() -> u32 {
2
}
fn default_unreachable_after_secs() -> u64 {
7
}
fn default_eviction_after_secs() -> u64 {
30
}
fn default_task_timeout_ms() -> u64 {
60_000
}
}
impl ValorApplicationConfig {
pub fn load() -> Result<Self> {
const CONFIG_CONTENT: &str = include_str!("../application.toml");
let config: ValorApplicationConfig = toml::from_str(CONFIG_CONTENT)?;
Ok(config)
}
pub fn hostname(&self) -> String {
"localhost".to_string()
}
pub fn cluster_cookie(&self) -> String {
self.cluster.cookie.clone()
}
pub fn master_port(&self) -> u16 {
self.master.port
}
pub fn worker_port(&self) -> u16 {
self.worker.port
}
pub fn tuning(&self) -> &ValorRuntimeTuning {
&self.runtime
}
}
#[derive(Parser, Debug, Clone)]
#[command(name = "righvalor")]
#[command(about = "RighValor AI Infrastructure for the Far Edge")]
#[command(version)]
pub struct ValorCli {
#[arg(long)]
pub id: String,
#[command(subcommand)]
pub command: ValorCommand,
#[arg(
long,
value_hint = ValueHint::FilePath,
help = "Path to the CA certificate file."
)]
pub ca_cert: Option<String>,
#[arg(
long,
value_hint = ValueHint::FilePath,
help = "Path to the peer certificate file."
)]
pub certificate: Option<String>,
#[arg(
long,
value_hint = ValueHint::FilePath,
help = "Path to the private key file."
)]
pub private_key: Option<String>,
#[arg(long, default_value = "/tmp/righvalor.sock")]
pub uds: PathBuf,
#[arg(long, value_hint = ValueHint::FilePath)]
pub service_toml: Option<PathBuf>,
}
#[derive(Subcommand, Debug, Clone)]
pub enum ValorCommand {
Master,
Worker,
RegisterWorker {
#[arg(long)]
worker_id: String,
#[arg(long)]
worker_ip: String,
},
}
#[derive(Debug, Clone)]
pub struct ValorConfig {
pub cli: ValorCli,
pub app: ValorApplicationConfig,
}
impl ValorConfig {
pub fn new() -> Result<Self> {
let cli = ValorCli::parse();
let app = ValorApplicationConfig::load()?;
Ok(ValorConfig { cli, app })
}
}