use std::{fmt, str::FromStr, time::Duration as StdDuration};
use reifydb_type::value::{Value, duration::Duration, r#type::Type};
use crate::common::CommitVersion;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ConfigKey {
OracleWindowSize,
OracleWaterMark,
RowTtlScanBatchSize,
RowTtlScanInterval,
}
impl ConfigKey {
pub fn all() -> &'static [Self] {
&[Self::OracleWindowSize, Self::OracleWaterMark, Self::RowTtlScanBatchSize, Self::RowTtlScanInterval]
}
pub fn default_value(&self) -> Value {
match self {
Self::OracleWindowSize => Value::Uint8(500),
Self::OracleWaterMark => Value::Uint8(20),
Self::RowTtlScanBatchSize => Value::Uint8(10000),
Self::RowTtlScanInterval => Value::Duration(Duration::from_seconds(60).unwrap()),
}
}
pub fn description(&self) -> &'static str {
match self {
Self::OracleWindowSize => "Number of transactions per conflict-detection window.",
Self::OracleWaterMark => "Number of conflict windows retained before cleanup is triggered.",
Self::RowTtlScanBatchSize => "Max rows to examine per batch during a row TTL scan.",
Self::RowTtlScanInterval => "How often the row TTL actor should scan for expired rows.",
}
}
pub fn requires_restart(&self) -> bool {
match self {
Self::OracleWindowSize => false,
Self::OracleWaterMark => false,
Self::RowTtlScanBatchSize => false,
Self::RowTtlScanInterval => false,
}
}
pub fn expected_types(&self) -> &'static [Type] {
match self {
Self::OracleWindowSize => &[Type::Uint8],
Self::OracleWaterMark => &[Type::Uint8],
Self::RowTtlScanBatchSize => &[Type::Uint8],
Self::RowTtlScanInterval => &[Type::Duration],
}
}
}
impl fmt::Display for ConfigKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::OracleWindowSize => write!(f, "ORACLE_WINDOW_SIZE"),
Self::OracleWaterMark => write!(f, "ORACLE_WATER_MARK"),
Self::RowTtlScanBatchSize => write!(f, "ROW_TTL_SCAN_BATCH_SIZE"),
Self::RowTtlScanInterval => write!(f, "ROW_TTL_SCAN_INTERVAL"),
}
}
}
impl FromStr for ConfigKey {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ORACLE_WINDOW_SIZE" => Ok(Self::OracleWindowSize),
"ORACLE_WATER_MARK" => Ok(Self::OracleWaterMark),
"ROW_TTL_SCAN_BATCH_SIZE" => Ok(Self::RowTtlScanBatchSize),
"ROW_TTL_SCAN_INTERVAL" => Ok(Self::RowTtlScanInterval),
_ => Err(format!("Unknown system configuration key: {}", s)),
}
}
}
#[derive(Debug, Clone)]
pub struct Config {
pub key: ConfigKey,
pub value: Value,
pub default_value: Value,
pub description: &'static str,
pub requires_restart: bool,
}
pub trait GetConfig: Send + Sync {
fn get_config(&self, key: ConfigKey) -> Value;
fn get_config_at(&self, key: ConfigKey, version: CommitVersion) -> Value;
fn get_config_uint8(&self, key: ConfigKey) -> u64 {
let val = self.get_config(key);
match val {
Value::Uint8(v) => v,
v => panic!("config key '{}' expected Uint8, got {:?}", key, v),
}
}
fn get_config_duration(&self, key: ConfigKey) -> StdDuration {
let val = self.get_config(key);
match val {
Value::Duration(v) => {
let total_nanos =
(v.get_days() as i128 * 24 * 3600 * 1_000_000_000) + (v.get_nanos() as i128);
StdDuration::from_nanos(total_nanos.max(0) as u64)
}
v => panic!("config key '{}' expected Duration, got {:?}", key, v),
}
}
}