use std::{fmt, marker::PhantomData, time::Duration};
use crate::Runtime;
use super::{
hooks::{Hook, Hooks},
Manager, Object, Pool, PoolConfig, QueueMode, Timeouts,
};
#[derive(Copy, Clone, Debug)]
pub enum BuildError {
NoRuntimeSpecified,
}
impl fmt::Display for BuildError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoRuntimeSpecified => write!(
f,
"Error occurred while building the pool: Timeouts require a runtime",
),
}
}
}
impl std::error::Error for BuildError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NoRuntimeSpecified => None,
}
}
}
#[must_use = "builder does nothing itself, use `.build()` to build it"]
pub struct PoolBuilder<M, W = Object<M>>
where
M: Manager,
W: From<Object<M>>,
{
pub(crate) manager: M,
pub(crate) config: PoolConfig,
pub(crate) runtime: Option<Runtime>,
pub(crate) hooks: Hooks<M>,
_wrapper: PhantomData<fn() -> W>,
}
impl<M, W> fmt::Debug for PoolBuilder<M, W>
where
M: fmt::Debug + Manager,
W: From<Object<M>>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PoolBuilder")
.field("manager", &self.manager)
.field("config", &self.config)
.field("runtime", &self.runtime)
.field("hooks", &self.hooks)
.field("_wrapper", &self._wrapper)
.finish()
}
}
impl<M, W> PoolBuilder<M, W>
where
M: Manager,
W: From<Object<M>>,
{
pub(crate) fn new(manager: M) -> Self {
Self {
manager,
config: PoolConfig::default(),
runtime: None,
hooks: Hooks::default(),
_wrapper: PhantomData,
}
}
pub fn build(self) -> Result<Pool<M, W>, BuildError> {
let t = &self.config.timeouts;
if (t.wait.is_some() || t.create.is_some() || t.recycle.is_some()) && self.runtime.is_none()
{
return Err(BuildError::NoRuntimeSpecified);
}
Ok(Pool::from_builder(self))
}
pub fn config(mut self, value: PoolConfig) -> Self {
self.config = value;
self
}
pub fn max_size(mut self, value: usize) -> Self {
self.config.max_size = value;
self
}
pub fn timeouts(mut self, value: Timeouts) -> Self {
self.config.timeouts = value;
self
}
pub fn wait_timeout(mut self, value: Option<Duration>) -> Self {
self.config.timeouts.wait = value;
self
}
pub fn create_timeout(mut self, value: Option<Duration>) -> Self {
self.config.timeouts.create = value;
self
}
pub fn recycle_timeout(mut self, value: Option<Duration>) -> Self {
self.config.timeouts.recycle = value;
self
}
pub fn queue_mode(mut self, value: QueueMode) -> Self {
self.config.queue_mode = value;
self
}
pub fn post_create(mut self, hook: impl Into<Hook<M>>) -> Self {
self.hooks.post_create.push(hook.into());
self
}
pub fn pre_recycle(mut self, hook: impl Into<Hook<M>>) -> Self {
self.hooks.pre_recycle.push(hook.into());
self
}
pub fn post_recycle(mut self, hook: impl Into<Hook<M>>) -> Self {
self.hooks.post_recycle.push(hook.into());
self
}
pub fn runtime(mut self, value: Runtime) -> Self {
self.runtime = Some(value);
self
}
}