use futures::{Stream, StreamExt};
use futures_time::time::Duration;
pub fn throttle_stream<ItemType, StreamType: Stream<Item = ItemType>>(
input_stream: StreamType,
elements_per_second: f64,
) -> impl Stream<Item = ItemType> {
let duration_between_elements = Duration::from_secs_f64(1.0 / elements_per_second);
let ticks = futures_time::stream::interval(duration_between_elements);
input_stream.zip(ticks).map(|(item, _)| item)
}
#[cfg(test)]
mod tests {
use super::*;
use futures::{stream, StreamExt};
#[tokio::test]
async fn constant_rate_stream() {
let frequency = 50.0;
let n_elements = 100;
let expected_duration_secs = 2.0; let tolerance = 0.1;
let unthrottled_stream = stream::iter(1..=n_elements);
let throttled_stream = throttle_stream(unthrottled_stream, frequency);
let start = std::time::Instant::now();
let observed_n_elements = throttled_stream.count().await;
let observed_duration = start.elapsed();
assert_eq!(
observed_n_elements, n_elements,
"Number of elements doesn't match"
);
assert!(
f64::abs(observed_duration.as_secs_f64() - expected_duration_secs) < tolerance,
"Unexpected duration while consuming a throttled stream"
);
}
}