mirror of
https://github.com/tower-rs/tower.git
synced 2025-10-02 15:25:11 +00:00
Update tower-load to std::future (#321)
This bumps tower-load to 0.3.0-alpha.1
This commit is contained in:
parent
db116d1937
commit
f8097a60f6
@ -9,7 +9,7 @@ members = [
|
|||||||
# "tower-hedge",
|
# "tower-hedge",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
# "tower-limit",
|
# "tower-limit",
|
||||||
# "tower-load",
|
"tower-load",
|
||||||
# "tower-load-shed",
|
# "tower-load-shed",
|
||||||
# "tower-reconnect",
|
# "tower-reconnect",
|
||||||
# "tower-retry",
|
# "tower-retry",
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
# 0.3.0-alpha.1
|
||||||
|
|
||||||
|
- Move to `std::future`
|
||||||
|
|
||||||
# 0.1.0 (unreleased)
|
# 0.1.0 (unreleased)
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
@ -8,13 +8,13 @@ name = "tower-load"
|
|||||||
# - README.md
|
# - README.md
|
||||||
# - Update CHANGELOG.md.
|
# - Update CHANGELOG.md.
|
||||||
# - Create "v0.1.x" git tag.
|
# - Create "v0.1.x" git tag.
|
||||||
version = "0.1.0"
|
version = "0.3.0-alpha.1"
|
||||||
authors = ["Tower Maintainers <team@tower-rs.com>"]
|
authors = ["Tower Maintainers <team@tower-rs.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/tower-rs/tower"
|
repository = "https://github.com/tower-rs/tower"
|
||||||
homepage = "https://github.com/tower-rs/tower"
|
homepage = "https://github.com/tower-rs/tower"
|
||||||
documentation = "https://docs.rs/tower-load/0.1.0"
|
documentation = "https://docs.rs/tower-load/0.3.0-alpha.1"
|
||||||
description = """
|
description = """
|
||||||
Strategies for measuring the load of a service
|
Strategies for measuring the load of a service
|
||||||
"""
|
"""
|
||||||
@ -23,11 +23,13 @@ edition = "2018"
|
|||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1.26"
|
futures-core-preview = "0.3.0-alpha.18"
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
tokio-timer = "0.2.4"
|
tokio-timer = "0.3.0-alpha.4"
|
||||||
tower-service = "0.2.0"
|
tower-service = "0.3.0-alpha.1"
|
||||||
tower-discover = "0.1.0"
|
tower-discover = { version = "0.3.0-alpha.1", path = "../tower-discover" }
|
||||||
|
pin-project = "0.4.0-alpha.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio-executor = "0.1.2"
|
tokio-test = "0.2.0-alpha.4"
|
||||||
|
futures-util-preview = "0.3.0-alpha.18"
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
//! A constant `Load` implementation. Primarily useful for testing.
|
//! A constant `Load` implementation. Primarily useful for testing.
|
||||||
|
|
||||||
use futures::{try_ready, Async, Poll};
|
use futures_core::ready;
|
||||||
|
use pin_project::pin_project;
|
||||||
|
use std::{
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use tower_discover::{Change, Discover};
|
use tower_discover::{Change, Discover};
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
|
|
||||||
use crate::Load;
|
use crate::Load;
|
||||||
|
|
||||||
/// Wraps a type so that `Load::load` returns a constant value.
|
/// Wraps a type so that `Load::load` returns a constant value.
|
||||||
|
#[pin_project]
|
||||||
pub struct Constant<T, M> {
|
pub struct Constant<T, M> {
|
||||||
inner: T,
|
inner: T,
|
||||||
load: M,
|
load: M,
|
||||||
@ -38,8 +44,8 @@ where
|
|||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = S::Future;
|
type Future = S::Future;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.inner.poll_ready()
|
self.inner.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
@ -48,20 +54,24 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Proxies `Discover` such that all changes are wrapped with a constant load.
|
/// Proxies `Discover` such that all changes are wrapped with a constant load.
|
||||||
impl<D: Discover, M: Copy> Discover for Constant<D, M> {
|
impl<D: Discover + Unpin, M: Copy> Discover for Constant<D, M> {
|
||||||
type Key = D::Key;
|
type Key = D::Key;
|
||||||
type Service = Constant<D::Service, M>;
|
type Service = Constant<D::Service, M>;
|
||||||
type Error = D::Error;
|
type Error = D::Error;
|
||||||
|
|
||||||
/// Yields the next discovery change set.
|
/// Yields the next discovery change set.
|
||||||
fn poll(&mut self) -> Poll<Change<D::Key, Self::Service>, D::Error> {
|
fn poll_discover(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Change<D::Key, Self::Service>, D::Error>> {
|
||||||
use self::Change::*;
|
use self::Change::*;
|
||||||
|
|
||||||
let change = match try_ready!(self.inner.poll()) {
|
let this = self.project();
|
||||||
Insert(k, svc) => Insert(k, Constant::new(svc, self.load)),
|
let change = match ready!(Pin::new(this.inner).poll_discover(cx))? {
|
||||||
|
Insert(k, svc) => Insert(k, Constant::new(svc, *this.load)),
|
||||||
Remove(k) => Remove(k),
|
Remove(k) => Remove(k),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Async::Ready(change))
|
Poll::Ready(Ok(change))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
use futures::{try_ready, Future, Poll};
|
use futures_core::ready;
|
||||||
|
use pin_project::pin_project;
|
||||||
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
/// Attaches `I`-typed instruments to `V` typed values.
|
/// Attaches `I`-typed instruments to `V` typed values.
|
||||||
///
|
///
|
||||||
@ -31,12 +37,10 @@ pub trait Instrument<H, V>: Clone {
|
|||||||
pub struct NoInstrument;
|
pub struct NoInstrument;
|
||||||
|
|
||||||
/// Attaches a `I`-typed instruments to the result of an `F`-typed `Future`.
|
/// Attaches a `I`-typed instruments to the result of an `F`-typed `Future`.
|
||||||
|
#[pin_project]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InstrumentFuture<F, I, H>
|
pub struct InstrumentFuture<F, I, H> {
|
||||||
where
|
#[pin]
|
||||||
F: Future,
|
|
||||||
I: Instrument<H, F::Item>,
|
|
||||||
{
|
|
||||||
future: F,
|
future: F,
|
||||||
handle: Option<H>,
|
handle: Option<H>,
|
||||||
instrument: I,
|
instrument: I,
|
||||||
@ -44,11 +48,7 @@ where
|
|||||||
|
|
||||||
// ===== impl InstrumentFuture =====
|
// ===== impl InstrumentFuture =====
|
||||||
|
|
||||||
impl<F, I, H> InstrumentFuture<F, I, H>
|
impl<F, I, H> InstrumentFuture<F, I, H> {
|
||||||
where
|
|
||||||
F: Future,
|
|
||||||
I: Instrument<H, F::Item>,
|
|
||||||
{
|
|
||||||
/// Wraps a future, instrumenting its value if successful.
|
/// Wraps a future, instrumenting its value if successful.
|
||||||
pub fn new(instrument: I, handle: H, future: F) -> Self {
|
pub fn new(instrument: I, handle: H, future: F) -> Self {
|
||||||
InstrumentFuture {
|
InstrumentFuture {
|
||||||
@ -59,18 +59,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, H> Future for InstrumentFuture<F, I, H>
|
impl<F, I, H, T, E> Future for InstrumentFuture<F, I, H>
|
||||||
where
|
where
|
||||||
F: Future,
|
F: Future<Output = Result<T, E>>,
|
||||||
I: Instrument<H, F::Item>,
|
I: Instrument<H, T>,
|
||||||
{
|
{
|
||||||
type Item = I::Output;
|
type Output = Result<I::Output, E>;
|
||||||
type Error = F::Error;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let rsp = try_ready!(self.future.poll());
|
let this = self.project();
|
||||||
let h = self.handle.take().expect("handle");
|
let rsp = ready!(this.future.poll(cx))?;
|
||||||
Ok(self.instrument.instrument(h, rsp).into())
|
let h = this.handle.take().expect("handle");
|
||||||
|
Poll::Ready(Ok(this.instrument.instrument(h, rsp)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Abstractions and utilties for measuring a service's load.
|
//! Abstractions and utilties for measuring a service's load.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/tower-load/0.1.0")]
|
#![doc(html_root_url = "https://docs.rs/tower-load/0.3.0-alpha.1")]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
use super::{Instrument, InstrumentFuture, NoInstrument};
|
use super::{Instrument, InstrumentFuture, NoInstrument};
|
||||||
use crate::Load;
|
use crate::Load;
|
||||||
use futures::{try_ready, Async, Poll};
|
use futures_core::ready;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
use pin_project::pin_project;
|
||||||
|
use std::{
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
@ -45,7 +50,9 @@ pub struct PeakEwma<S, I = NoInstrument> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a `D`-typed stream of discovery updates with `PeakEwma`.
|
/// Wraps a `D`-typed stream of discovery updates with `PeakEwma`.
|
||||||
|
#[pin_project]
|
||||||
pub struct PeakEwmaDiscover<D, I = NoInstrument> {
|
pub struct PeakEwmaDiscover<D, I = NoInstrument> {
|
||||||
|
#[pin]
|
||||||
discover: D,
|
discover: D,
|
||||||
decay_ns: f64,
|
decay_ns: f64,
|
||||||
default_rtt: Duration,
|
default_rtt: Duration,
|
||||||
@ -108,21 +115,25 @@ where
|
|||||||
type Service = PeakEwma<D::Service, I>;
|
type Service = PeakEwma<D::Service, I>;
|
||||||
type Error = D::Error;
|
type Error = D::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Change<D::Key, Self::Service>, D::Error> {
|
fn poll_discover(
|
||||||
let change = match try_ready!(self.discover.poll()) {
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Change<D::Key, Self::Service>, D::Error>> {
|
||||||
|
let this = self.project();
|
||||||
|
let change = match ready!(this.discover.poll_discover(cx))? {
|
||||||
Change::Remove(k) => Change::Remove(k),
|
Change::Remove(k) => Change::Remove(k),
|
||||||
Change::Insert(k, svc) => {
|
Change::Insert(k, svc) => {
|
||||||
let peak_ewma = PeakEwma::new(
|
let peak_ewma = PeakEwma::new(
|
||||||
svc,
|
svc,
|
||||||
self.default_rtt,
|
*this.default_rtt,
|
||||||
self.decay_ns,
|
*this.decay_ns,
|
||||||
self.instrument.clone(),
|
this.instrument.clone(),
|
||||||
);
|
);
|
||||||
Change::Insert(k, peak_ewma)
|
Change::Insert(k, peak_ewma)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Async::Ready(change))
|
Poll::Ready(Ok(change))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +167,8 @@ where
|
|||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = InstrumentFuture<S::Future, I, Handle>;
|
type Future = InstrumentFuture<S::Future, I, Handle>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.service.poll_ready()
|
self.service.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
@ -293,12 +304,16 @@ fn nanos(d: Duration) -> f64 {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use futures::{future, Future, Poll};
|
use futures_util::future;
|
||||||
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tokio_executor::enter;
|
use tokio_test::{assert_ready, assert_ready_ok};
|
||||||
use tokio_timer::clock;
|
use tokio_timer::clock;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -307,10 +322,10 @@ mod tests {
|
|||||||
impl Service<()> for Svc {
|
impl Service<()> for Svc {
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = ();
|
type Error = ();
|
||||||
type Future = future::FutureResult<(), ()>;
|
type Future = future::Ready<Result<(), ()>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), ()> {
|
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), ()>> {
|
||||||
Ok(().into())
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, (): ()) -> Self::Future {
|
fn call(&mut self, (): ()) -> Self::Future {
|
||||||
@ -332,8 +347,7 @@ mod tests {
|
|||||||
let time = Arc::new(Mutex::new(Instant::now()));
|
let time = Arc::new(Mutex::new(Instant::now()));
|
||||||
let clock = clock::Clock::new_with_now(Now(time.clone()));
|
let clock = clock::Clock::new_with_now(Now(time.clone()));
|
||||||
|
|
||||||
let mut enter = enter().expect("enter");
|
clock::with_default(&clock, || {
|
||||||
clock::with_default(&clock, &mut enter, |_| {
|
|
||||||
let svc = PeakEwma::new(
|
let svc = PeakEwma::new(
|
||||||
Svc,
|
Svc,
|
||||||
Duration::from_millis(10),
|
Duration::from_millis(10),
|
||||||
@ -360,38 +374,39 @@ mod tests {
|
|||||||
let time = Arc::new(Mutex::new(Instant::now()));
|
let time = Arc::new(Mutex::new(Instant::now()));
|
||||||
let clock = clock::Clock::new_with_now(Now(time.clone()));
|
let clock = clock::Clock::new_with_now(Now(time.clone()));
|
||||||
|
|
||||||
let mut enter = enter().expect("enter");
|
clock::with_default(&clock, || {
|
||||||
clock::with_default(&clock, &mut enter, |_| {
|
tokio_test::task::mock(|cx| {
|
||||||
let mut svc = PeakEwma::new(
|
let mut svc = PeakEwma::new(
|
||||||
Svc,
|
Svc,
|
||||||
Duration::from_millis(20),
|
Duration::from_millis(20),
|
||||||
NANOS_PER_MILLI * 1_000.0,
|
NANOS_PER_MILLI * 1_000.0,
|
||||||
NoInstrument,
|
NoInstrument,
|
||||||
);
|
);
|
||||||
assert_eq!(svc.load(), Cost(20.0 * NANOS_PER_MILLI));
|
assert_eq!(svc.load(), Cost(20.0 * NANOS_PER_MILLI));
|
||||||
|
|
||||||
*time.lock().unwrap() += Duration::from_millis(100);
|
*time.lock().unwrap() += Duration::from_millis(100);
|
||||||
let rsp0 = svc.call(());
|
let mut rsp0 = svc.call(());
|
||||||
assert!(svc.load() > Cost(20.0 * NANOS_PER_MILLI));
|
assert!(svc.load() > Cost(20.0 * NANOS_PER_MILLI));
|
||||||
|
|
||||||
*time.lock().unwrap() += Duration::from_millis(100);
|
*time.lock().unwrap() += Duration::from_millis(100);
|
||||||
let rsp1 = svc.call(());
|
let mut rsp1 = svc.call(());
|
||||||
assert!(svc.load() > Cost(40.0 * NANOS_PER_MILLI));
|
assert!(svc.load() > Cost(40.0 * NANOS_PER_MILLI));
|
||||||
|
|
||||||
*time.lock().unwrap() += Duration::from_millis(100);
|
*time.lock().unwrap() += Duration::from_millis(100);
|
||||||
let () = rsp0.wait().unwrap();
|
let () = assert_ready_ok!(Pin::new(&mut rsp0).poll(cx));
|
||||||
assert_eq!(svc.load(), Cost(400_000_000.0));
|
assert_eq!(svc.load(), Cost(400_000_000.0));
|
||||||
|
|
||||||
*time.lock().unwrap() += Duration::from_millis(100);
|
*time.lock().unwrap() += Duration::from_millis(100);
|
||||||
let () = rsp1.wait().unwrap();
|
let () = assert_ready_ok!(Pin::new(&mut rsp1).poll(cx));
|
||||||
assert_eq!(svc.load(), Cost(200_000_000.0));
|
assert_eq!(svc.load(), Cost(200_000_000.0));
|
||||||
|
|
||||||
// Check that values decay as time elapses
|
// Check that values decay as time elapses
|
||||||
*time.lock().unwrap() += Duration::from_secs(1);
|
*time.lock().unwrap() += Duration::from_secs(1);
|
||||||
assert!(svc.load() < Cost(100_000_000.0));
|
assert!(svc.load() < Cost(100_000_000.0));
|
||||||
|
|
||||||
*time.lock().unwrap() += Duration::from_secs(10);
|
*time.lock().unwrap() += Duration::from_secs(10);
|
||||||
assert!(svc.load() < Cost(100_000.0));
|
assert!(svc.load() < Cost(100_000.0));
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
|
|
||||||
use super::{Instrument, InstrumentFuture, NoInstrument};
|
use super::{Instrument, InstrumentFuture, NoInstrument};
|
||||||
use crate::Load;
|
use crate::Load;
|
||||||
use futures::{try_ready, Async, Poll};
|
use futures_core::ready;
|
||||||
|
use pin_project::pin_project;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::{
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use tower_discover::{Change, Discover};
|
use tower_discover::{Change, Discover};
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
|
|
||||||
@ -21,8 +26,10 @@ pub struct PendingRequests<S, I = NoInstrument> {
|
|||||||
struct RefCount(Arc<()>);
|
struct RefCount(Arc<()>);
|
||||||
|
|
||||||
/// Wraps `inner`'s services with `PendingRequests`.
|
/// Wraps `inner`'s services with `PendingRequests`.
|
||||||
|
#[pin_project]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PendingRequestsDiscover<D, I = NoInstrument> {
|
pub struct PendingRequestsDiscover<D, I = NoInstrument> {
|
||||||
|
#[pin]
|
||||||
discover: D,
|
discover: D,
|
||||||
instrument: I,
|
instrument: I,
|
||||||
}
|
}
|
||||||
@ -69,8 +76,8 @@ where
|
|||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = InstrumentFuture<S::Future, I, Handle>;
|
type Future = InstrumentFuture<S::Future, I, Handle>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.service.poll_ready()
|
self.service.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
@ -109,15 +116,19 @@ where
|
|||||||
type Error = D::Error;
|
type Error = D::Error;
|
||||||
|
|
||||||
/// Yields the next discovery change set.
|
/// Yields the next discovery change set.
|
||||||
fn poll(&mut self) -> Poll<Change<D::Key, Self::Service>, D::Error> {
|
fn poll_discover(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Result<Change<D::Key, Self::Service>, D::Error>> {
|
||||||
use self::Change::*;
|
use self::Change::*;
|
||||||
|
|
||||||
let change = match try_ready!(self.discover.poll()) {
|
let this = self.project();
|
||||||
Insert(k, svc) => Insert(k, PendingRequests::new(svc, self.instrument.clone())),
|
let change = match ready!(this.discover.poll_discover(cx))? {
|
||||||
|
Insert(k, svc) => Insert(k, PendingRequests::new(svc, this.instrument.clone())),
|
||||||
Remove(k) => Remove(k),
|
Remove(k) => Remove(k),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Async::Ready(change))
|
Poll::Ready(Ok(change))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,16 +143,17 @@ impl RefCount {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use futures::{future, Future, Poll};
|
use futures_util::future;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
struct Svc;
|
struct Svc;
|
||||||
impl Service<()> for Svc {
|
impl Service<()> for Svc {
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = ();
|
type Error = ();
|
||||||
type Future = future::FutureResult<(), ()>;
|
type Future = future::Ready<Result<(), ()>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), ()> {
|
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), ()>> {
|
||||||
Ok(().into())
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, (): ()) -> Self::Future {
|
fn call(&mut self, (): ()) -> Self::Future {
|
||||||
@ -160,10 +172,10 @@ mod tests {
|
|||||||
let rsp1 = svc.call(());
|
let rsp1 = svc.call(());
|
||||||
assert_eq!(svc.load(), Count(2));
|
assert_eq!(svc.load(), Count(2));
|
||||||
|
|
||||||
let () = rsp0.wait().unwrap();
|
let () = tokio_test::block_on(rsp0).unwrap();
|
||||||
assert_eq!(svc.load(), Count(1));
|
assert_eq!(svc.load(), Count(1));
|
||||||
|
|
||||||
let () = rsp1.wait().unwrap();
|
let () = tokio_test::block_on(rsp1).unwrap();
|
||||||
assert_eq!(svc.load(), Count(0));
|
assert_eq!(svc.load(), Count(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,12 +195,12 @@ mod tests {
|
|||||||
|
|
||||||
let rsp = svc.call(());
|
let rsp = svc.call(());
|
||||||
assert_eq!(svc.load(), Count(1));
|
assert_eq!(svc.load(), Count(1));
|
||||||
let i0 = rsp.wait().unwrap();
|
let i0 = tokio_test::block_on(rsp).unwrap();
|
||||||
assert_eq!(svc.load(), Count(1));
|
assert_eq!(svc.load(), Count(1));
|
||||||
|
|
||||||
let rsp = svc.call(());
|
let rsp = svc.call(());
|
||||||
assert_eq!(svc.load(), Count(2));
|
assert_eq!(svc.load(), Count(2));
|
||||||
let i1 = rsp.wait().unwrap();
|
let i1 = tokio_test::block_on(rsp).unwrap();
|
||||||
assert_eq!(svc.load(), Count(2));
|
assert_eq!(svc.load(), Count(2));
|
||||||
|
|
||||||
drop(i1);
|
drop(i1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user