use std::collections::HashMap;
use std::path::Path;
use std::sync::atomic::{AtomicBool, AtomicU64};
use std::sync::{Arc, Mutex};
use redb::Database;
use redb::backends::InMemoryBackend;
use tokio::task::JoinSet;
use crate::error::EngineError;
use crate::retry::RetryPolicy;
pub struct EngineBuilder<S = NoStore> {
pub(super) store: S,
pub(super) default_retry: Option<RetryPolicy>,
pub(super) resume_on_start: bool,
}
#[doc(hidden)]
pub struct NoStore;
#[doc(hidden)]
pub struct HasStore(pub(super) Database);
impl EngineBuilder<NoStore> {
#[must_use]
#[expect(clippy::missing_panics_doc)]
pub fn in_memory(self) -> EngineBuilder<HasStore> {
let db = Database::builder()
.create_with_backend(InMemoryBackend::new())
.expect("in-memory database creation should not fail");
EngineBuilder {
store: HasStore(db),
default_retry: self.default_retry,
resume_on_start: self.resume_on_start,
}
}
pub fn open(self, path: impl AsRef<Path>) -> Result<EngineBuilder<HasStore>, EngineError> {
let db = Database::create(path)?;
Ok(EngineBuilder {
store: HasStore(db),
default_retry: self.default_retry,
resume_on_start: self.resume_on_start,
})
}
#[must_use]
pub fn default_retry(mut self, policy: RetryPolicy) -> Self {
self.default_retry = Some(policy);
self
}
#[must_use]
pub fn resume_on_start(mut self, enabled: bool) -> Self {
self.resume_on_start = enabled;
self
}
}
impl EngineBuilder<HasStore> {
#[must_use]
pub fn default_retry(mut self, policy: RetryPolicy) -> Self {
self.default_retry = Some(policy);
self
}
#[must_use]
pub fn resume_on_start(mut self, enabled: bool) -> Self {
self.resume_on_start = enabled;
self
}
#[must_use]
pub fn build(self) -> super::Engine {
super::Engine {
db: Arc::new(self.store.0),
workflows: HashMap::new(),
running: Arc::new(AtomicBool::new(false)),
tasks: Arc::new(tokio::sync::Mutex::new(JoinSet::new())),
timer_serial: Arc::new(AtomicU64::new(0)),
default_retry: self.default_retry,
resume_on_start: self.resume_on_start,
senders: Arc::new(Mutex::new(HashMap::new())),
}
}
}