use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
mpsc,
};
use std::time::{Duration, Instant};
use timerwheel::prelude::*;
struct CountingTimerSink {
observations: Arc<AtomicUsize>,
}
impl TimerMetricSink for CountingTimerSink {
fn observe_metrics(&self, _metrics: TimerMetrics) {
self.observations.fetch_add(1, Ordering::Relaxed);
}
}
struct CountingExecutorSink {
observations: Arc<AtomicUsize>,
}
impl ExecutorMetricSink for CountingExecutorSink {
fn observe_metrics(&self, _metrics: ExecutorMetrics) {
self.observations.fetch_add(1, Ordering::Relaxed);
}
}
#[test]
fn prelude_imports_core_timer_executor_and_metric_sink_aliases() {
let timer_observations = Arc::new(AtomicUsize::new(0));
let timer: Timer = Timer::builder()
.tick(Duration::from_millis(1))
.bucket_count(64)
.metric_sink(CountingTimerSink {
observations: Arc::clone(&timer_observations),
})
.build()
.expect("timer builds");
let (timer_tx, timer_rx) = mpsc::channel();
let timeout: Timeout = timer
.schedule(Duration::from_millis(5), move || {
timer_tx.send(()).expect("send succeeds");
})
.expect("schedule succeeds");
timer_rx
.recv_timeout(Duration::from_secs(1))
.expect("timeout should fire");
let deadline = Instant::now() + Duration::from_secs(1);
while !timeout.is_expired() && Instant::now() < deadline {
std::thread::sleep(Duration::from_millis(1));
}
assert!(timeout.is_expired());
assert_eq!(BackpressurePolicy::Reject, BackpressurePolicy::Reject);
assert_eq!(ExpiredTaskPolicy::Retry, ExpiredTaskPolicy::Retry);
assert!(timer.metrics().scheduled_timeouts >= 1);
assert!(timer_observations.load(Ordering::Relaxed) > 0);
timer.shutdown().expect("timer shuts down");
let executor_observations = Arc::new(AtomicUsize::new(0));
let pool: Pool = Pool::builder()
.workers(1)
.queue_capacity(8)
.reject_policy(RejectPolicy::Reject)
.metric_sink(CountingExecutorSink {
observations: Arc::clone(&executor_observations),
})
.build()
.expect("pool builds");
let (pool_tx, pool_rx) = mpsc::channel();
pool.execute(move || {
pool_tx.send(()).expect("send succeeds");
})
.expect("pool accepts task");
pool_rx
.recv_timeout(Duration::from_secs(1))
.expect("pool task should run");
assert!(pool.metrics().submitted_tasks >= 1);
assert!(executor_observations.load(Ordering::Relaxed) > 0);
pool.shutdown().expect("pool shuts down");
}
#[cfg(feature = "tokio")]
#[test]
fn prelude_imports_tokio_aliases_when_feature_is_enabled() {
fn assert_tokio_timer_builder(_: TokioTimerBuilder) {}
let runtime = tokio::runtime::Runtime::new().expect("runtime builds");
runtime.block_on(async {
let executor = TokioExecutor::current().expect("tokio executor builds");
executor.shutdown().expect("tokio executor shuts down");
assert_tokio_timer_builder(TokioTimer::builder());
});
}