use crate::context::{Context, RedisConfig};
use crate::error::Result;
use crate::state::FilesystemStateManager;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ContextBuilder {
node_id: String,
instance: Option<String>,
redis_url: Option<String>,
state_dir: Option<PathBuf>,
redis_config: Option<RedisConfig>,
}
impl ContextBuilder {
pub fn new(node_id: impl Into<String>) -> Self {
Self {
node_id: node_id.into(),
instance: None,
redis_url: None,
state_dir: None,
redis_config: None,
}
}
pub fn with_instance(mut self, instance: impl Into<String>) -> Self {
self.instance = Some(instance.into());
self
}
crate::builder_setter!(
into_some, with_redis, redis_url, impl Into<String>
);
crate::builder_setter!(
into_some, with_state_dir, state_dir, impl Into<PathBuf>
);
pub fn with_custom_redis<F>(mut self, configure: F) -> Self
where
F: FnOnce(&mut RedisConfig),
{
let mut config = RedisConfig::default();
configure(&mut config);
self.redis_config = Some(config);
self
}
pub async fn build(self) -> Result<Context> {
if let Some(redis_url) = &self.redis_url {
std::env::set_var("MECHA10_REDIS_URL", redis_url);
}
let mut ctx = Context::new(&self.node_id).await?;
if let Some(instance) = self.instance {
ctx = ctx.with_instance(&instance);
}
if let Some(state_dir) = self.state_dir {
let state_manager = FilesystemStateManager::new(&state_dir).await?;
let concrete = Arc::new(crate::state::ConcreteStateManager::Filesystem(state_manager));
ctx.set_state_manager(concrete).await;
}
Ok(ctx)
}
}
impl Context {
pub fn builder(node_id: impl Into<String>) -> ContextBuilder {
ContextBuilder::new(node_id)
}
}
impl ContextBuilder {
pub fn local_dev(node_id: impl Into<String>) -> Self {
Self::new(node_id)
.with_redis("redis://localhost:6379")
.with_state_dir("./data/state")
}
pub fn production(node_id: impl Into<String>) -> Self {
let state_dir = std::env::var("MECHA10_STATE_DIR").unwrap_or_else(|_| "/var/lib/mecha10".to_string());
Self::new(node_id).with_state_dir(state_dir).with_custom_redis(|cfg| {
cfg.max_connections = 50;
cfg.connection_timeout_ms = 3000;
})
}
pub fn test(node_id: impl Into<String>) -> Self {
let redis_url = std::env::var("TEST_REDIS_URL").unwrap_or_else(|_| "redis://localhost:6379".to_string());
let state_dir = std::env::temp_dir().join("mecha10-test");
Self::new(node_id).with_redis(redis_url).with_state_dir(state_dir)
}
}