use std::{
sync::Arc,
task::{Context, Poll},
time::Duration,
};
use futures_core::Stream;
#[cfg(feature = "sleep")]
use crate::backend::ext::poll_strategy::{BackoffConfig, IntervalStrategy};
use crate::backend::ext::poll_strategy::{
BoxedPollStrategy, PollSnapshot, PollStrategy, StreamStrategy,
};
#[derive(Clone, Default)]
pub struct Strategy {
strategies: Arc<std::sync::Mutex<Vec<BoxedPollStrategy>>>,
}
impl Strategy {
#[must_use]
pub fn new() -> Self {
Self {
strategies: Default::default(),
}
}
#[must_use]
pub fn apply<S>(self, strategy: S) -> Self
where
S: PollStrategy + Send + Sync + 'static,
{
self.strategies.lock().unwrap().push(Box::new(strategy));
self
}
#[must_use]
pub fn stream<S>(self, stream: S) -> Self
where
S: Stream + Unpin + Send + Sync + 'static,
{
self.apply(StreamStrategy::new(stream))
}
#[must_use]
#[cfg(feature = "sleep")]
pub fn interval(self, period: Duration) -> Self {
self.apply(IntervalStrategy::new(period))
}
#[must_use]
#[cfg(feature = "sleep")]
pub fn interval_with_backoff(self, period: Duration, backoff: BackoffConfig) -> Self {
self.apply(IntervalStrategy::new(period).with_backoff(backoff))
}
}
impl std::fmt::Debug for Strategy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MultiStrategy")
.field("strategies", &self.strategies.lock().unwrap().len())
.finish()
}
}
impl PollStrategy for Strategy {
fn poll_drive(&mut self, cx: &mut Context<'_>, worker: &PollSnapshot) -> Poll<Option<()>> {
for strategy in &mut self.strategies.lock().unwrap().iter_mut() {
if strategy.poll_drive(cx, worker).is_ready() {
return Poll::Ready(Some(()));
}
}
Poll::Pending
}
}