use std::sync::Arc;
use std::time::Duration;
use crate::error::{Error, Result};
use crate::executor;
use crate::policy::{BackpressurePolicy, ExpiredTaskPolicy};
use crate::timer::metric_sink::{MetricSink, NoopMetricSink};
use crate::timer::scheduler::Timer;
#[derive(Clone)]
pub struct TimerBuilder {
pub(crate) tick: Duration,
pub(crate) bucket_count: usize,
pub(crate) command_capacity: usize,
pub(crate) max_pending: usize,
pub(crate) backpressure_policy: BackpressurePolicy,
pub(crate) expired_task_policy: ExpiredTaskPolicy,
pub(crate) expired_task_retry: Duration,
pub(crate) executor: Option<Arc<dyn executor::Executor>>,
pub(crate) metric_sink: Arc<dyn MetricSink>,
pub(crate) owns_executor: bool,
}
impl Default for TimerBuilder {
fn default() -> Self {
let tick = Duration::from_millis(1);
Self {
tick,
bucket_count: 512,
command_capacity: 65_536,
max_pending: 1_000_000,
backpressure_policy: BackpressurePolicy::Reject,
expired_task_policy: ExpiredTaskPolicy::Reject,
expired_task_retry: tick,
executor: None,
metric_sink: Arc::new(NoopMetricSink),
owns_executor: true,
}
}
}
impl TimerBuilder {
pub fn tick(mut self, tick: Duration) -> Self {
self.tick = tick;
self
}
pub fn bucket_count(mut self, bucket_count: usize) -> Self {
self.bucket_count = bucket_count;
self
}
pub fn command_capacity(mut self, command_capacity: usize) -> Self {
self.command_capacity = command_capacity;
self
}
pub fn max_pending(mut self, max_pending: usize) -> Self {
self.max_pending = max_pending;
self
}
pub fn backpressure_policy(mut self, policy: BackpressurePolicy) -> Self {
self.backpressure_policy = policy;
self
}
pub fn expired_task_policy(mut self, policy: ExpiredTaskPolicy) -> Self {
self.expired_task_policy = policy;
self
}
pub fn expired_task_retry(mut self, retry: Duration) -> Self {
self.expired_task_retry = retry;
self
}
pub fn executor(mut self, executor: Arc<dyn executor::Executor>) -> Self {
self.executor = Some(executor);
self.owns_executor = false;
self
}
pub fn metric_sink<S>(mut self, metric_sink: S) -> Self
where
S: MetricSink,
{
self.metric_sink = Arc::new(metric_sink);
self
}
pub fn build(self) -> Result<Timer> {
if self.tick.is_zero() {
return Err(Error::InvalidConfig("tick must be greater than zero"));
}
if self.bucket_count == 0 {
return Err(Error::InvalidConfig(
"bucket_count must be greater than zero",
));
}
if self.command_capacity == 0 {
return Err(Error::InvalidConfig(
"command_capacity must be greater than zero",
));
}
if self.max_pending == 0 {
return Err(Error::InvalidConfig(
"max_pending must be greater than zero",
));
}
if self.expired_task_retry.is_zero() {
return Err(Error::InvalidConfig(
"expired_task_retry must be greater than zero",
));
}
Timer::new(self)
}
}