use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
use taquba::Queue;
use taquba::object_store::ObjectStore;
use taquba_workflow::{RunnerHandle, WorkflowRuntime};
use tokio_util::sync::CancellationToken;
use crate::dispatch::Dispatch;
use crate::hook::RecordHook;
use crate::operator::OperatorSet;
use crate::store::store_path;
pub type PoolRuntime = WorkflowRuntime<Dispatch, RecordHook>;
pub struct Pools {
runtimes: HashMap<String, PoolRuntime>,
}
pub struct PoolsBuilder {
queue: Arc<Queue>,
store: Arc<dyn ObjectStore>,
dispatch: Dispatch,
hook: RecordHook,
poll_interval: Duration,
memo_retention: Duration,
store_prefix: String,
pools: Vec<(String, usize)>,
}
impl PoolsBuilder {
pub fn pool(mut self, name: impl Into<String>, max_concurrent_steps: usize) -> Self {
self.pools.push((name.into(), max_concurrent_steps));
self
}
pub fn poll_interval(mut self, interval: Duration) -> Self {
self.poll_interval = interval;
self
}
pub fn memo_retention(mut self, retention: Duration) -> Self {
self.memo_retention = retention;
self
}
pub fn store_prefix(mut self, prefix: impl Into<String>) -> Self {
self.store_prefix = prefix.into();
self
}
pub fn build(self) -> Pools {
let runtimes = self
.pools
.into_iter()
.map(|(name, concurrency)| {
let runtime = WorkflowRuntime::builder(
self.queue.clone(),
self.store.clone(),
self.dispatch.clone(),
self.hook.clone(),
)
.queue_name(format!("swale-pool-{name}"))
.memo_prefix(store_path(&self.store_prefix, &format!("memos/{name}")))
.max_concurrent_steps(concurrency)
.poll_interval(self.poll_interval)
.memo_retention(self.memo_retention)
.build();
(name, runtime)
})
.collect();
Pools { runtimes }
}
}
impl Pools {
pub fn builder(
queue: Arc<Queue>,
store: Arc<dyn ObjectStore>,
operators: Arc<OperatorSet>,
hook: RecordHook,
) -> PoolsBuilder {
let dispatch = Dispatch::new(operators, queue.clock());
PoolsBuilder {
queue,
store,
dispatch,
hook,
poll_interval: Duration::from_millis(250),
memo_retention: Duration::from_secs(7 * 86_400),
store_prefix: String::new(),
pools: Vec::new(),
}
}
pub fn runtime(&self, name: &str) -> Option<&PoolRuntime> {
self.runtimes.get(name)
}
pub fn spawn(&self, shutdown: &CancellationToken) -> Vec<RunnerHandle> {
self.runtimes
.values()
.map(|runtime| runtime.spawn(shutdown.clone().cancelled_owned()))
.collect()
}
}