use std::sync::atomic::{AtomicU64, Ordering};
use uuid::Uuid;
#[derive(Debug, Clone, Default)]
pub struct IdConfig {
pub seed: Option<u64>,
pub prefix: Option<String>,
pub include_timestamp: bool,
pub use_counter: bool,
}
#[derive(Debug, Default)]
pub struct IdGenerator {
config: IdConfig,
counter: AtomicU64,
}
impl IdGenerator {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_config(config: IdConfig) -> Self {
Self {
config,
counter: AtomicU64::new(0),
}
}
#[must_use]
pub fn generate_id(&self) -> String {
let mut id = self.base_id();
if self.config.include_timestamp {
let ts = chrono::Utc::now().timestamp();
id = format!("{id}-t{ts}");
}
if let Some(p) = &self.config.prefix {
id = format!("{p}-{id}");
}
id
}
#[must_use]
pub fn generate_id_with_prefix(&self, prefix: &str) -> String {
format!("{prefix}-{}", self.base_id())
}
#[must_use]
pub fn generate_run_id(&self) -> String {
self.generate_id_with_prefix("run")
}
#[must_use]
pub fn generate_step_id(&self) -> String {
self.generate_id_with_prefix("step")
}
#[must_use]
pub fn generate_node_id(&self) -> String {
self.generate_id_with_prefix("node")
}
#[must_use]
pub fn generate_session_id(&self) -> String {
self.generate_id_with_prefix("session")
}
fn base_id(&self) -> String {
match (self.config.seed, self.config.use_counter) {
(Some(seed), true) => {
let n = self.counter.fetch_add(1, Ordering::Relaxed);
format!("seeded-{seed}-{n}")
}
(Some(seed), false) => format!("seeded-{seed}"),
(None, true) => {
let n = self.counter.fetch_add(1, Ordering::Relaxed);
format!("counter-{n}")
}
(None, false) => Uuid::new_v4().to_string(),
}
}
}