|
|
@ -1,6 +1,10 @@
|
|
|
|
//! The actual running task
|
|
|
|
//! The actual running task
|
|
|
|
use super::*;
|
|
|
|
use super::*;
|
|
|
|
use futures::prelude::*;
|
|
|
|
use futures::{
|
|
|
|
|
|
|
|
prelude::*,
|
|
|
|
|
|
|
|
future::OptionFuture,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
|
|
pub type SupervisorError = (); //TODO
|
|
|
|
pub type SupervisorError = (); //TODO
|
|
|
|
pub type Error = (); // TODO
|
|
|
|
pub type Error = (); // TODO
|
|
|
@ -13,21 +17,37 @@ pub(super) fn spawn_supervisor(service: Service) -> JoinHandle<Result<(), Superv
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Delay for a number of **nanoseconds** between the specified bounds
|
|
|
|
|
|
|
|
fn jitter_for(bounds: (u64, u64)) -> OptionFuture<impl Future<Output = ()> + 'static>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match bounds.jitter() {
|
|
|
|
|
|
|
|
0 => None.into(),
|
|
|
|
|
|
|
|
x => Some(tokio::time::delay_for(Duration::from_nanos(x))).into()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn spawn_slave(service: Service) -> JoinHandle<Result<(), Error>>
|
|
|
|
fn spawn_slave(service: Service) -> JoinHandle<Result<(), Error>>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let Service { inner: service, rx } = service;
|
|
|
|
let Service { inner: service, rx } = service;
|
|
|
|
tokio::spawn(async move {
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
|
|
|
let cfg = service.opt.as_ref();
|
|
|
|
|
|
|
|
|
|
|
|
let mut rx = rx
|
|
|
|
let mut rx = rx
|
|
|
|
.chunk(10) // TODO: from config
|
|
|
|
.chunk(cfg.req_dispatch_chunk.into())
|
|
|
|
.lag(duration!(10 ms)); // TODO: from config
|
|
|
|
.lag(cfg.req_dispatch_delay.unwrap_or(Duration::ZERO));
|
|
|
|
let mut timeout = tokio::time::interval(duration!(200 ms)); // TODO: from config
|
|
|
|
let mut timeout = cfg.req_dispatch_force_timeout.map(tokio::time::interval);
|
|
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
loop {
|
|
|
|
tokio::select! {
|
|
|
|
tokio::select! {
|
|
|
|
block = rx.next() => {
|
|
|
|
block = rx.next() => {
|
|
|
|
match block {
|
|
|
|
match block {
|
|
|
|
Some(block) => {
|
|
|
|
Some(block) => {
|
|
|
|
// TODO: Filter and/or process this block
|
|
|
|
if let Some(bounds) = cfg.req_dispatch_jitter.and_then(|x| (x.0 + x.1 > 0).then(|| x)) {
|
|
|
|
|
|
|
|
// Jitter delay.
|
|
|
|
|
|
|
|
jitter_for(bounds).await;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Filter and then/or process this block
|
|
|
|
},
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
None => {
|
|
|
|
// Reached the end of stream, exit gracefully.
|
|
|
|
// Reached the end of stream, exit gracefully.
|
|
|
@ -35,7 +55,7 @@ fn spawn_slave(service: Service) -> JoinHandle<Result<(), Error>>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ = timeout.tick() => {
|
|
|
|
_ = OptionFuture::from(timeout.as_mut().map(|x| x.tick())), if timeout.is_some() => {
|
|
|
|
// Cause the `rx` to release a non-full chunk.
|
|
|
|
// Cause the `rx` to release a non-full chunk.
|
|
|
|
rx.get_mut().push_now();
|
|
|
|
rx.get_mut().push_now();
|
|
|
|
}
|
|
|
|
}
|
|
|
|