Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream: add WatchStream::from_changes, add testing, etc. #5432

Merged
merged 22 commits into from
Feb 19, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
afc73fb
stream: add `WatchStream::new_on_changed`, add testing, etc.
brodycj Feb 6, 2023
83888af
FIXUP: remove extra parens in test case
brodycj Feb 6, 2023
f988a46
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 9, 2023
a9482cd
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 10, 2023
bdc09c0
rework test
brodycj Feb 10, 2023
88d2feb
fix imports & fmt
brodycj Feb 10, 2023
48bbfd4
fix an import again
brodycj Feb 10, 2023
048bd05
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 12, 2023
b8c31ea
simplify test with utility from tokio-test
brodycj Feb 12, 2023
6ca8990
add example with new_on_changed & add comment to another example
brodycj Feb 13, 2023
2db6ccb
add another test to the example
brodycj Feb 13, 2023
edc4fde
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 14, 2023
1ce7bbb
update sample comment & first_poll variable name
brodycj Feb 14, 2023
eef3db9
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 15, 2023
95870cd
sample poll test down to 1 line & update comment
brodycj Feb 15, 2023
63e276a
use `now_or_never` (needs `futures_util::future::FutureExt`)
Feb 17, 2023
f413e2a
update imports
brodycj Feb 17, 2023
67d4c87
rename function to `from_changes`
brodycj Feb 17, 2023
28c2040
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 17, 2023
0da26da
Merge branch 'master' of https://github.com/tokio-rs/tokio into new-w…
brodycj Feb 19, 2023
f1ddac9
remove futures-test not needed from dev dependencies
brodycj Feb 19, 2023
7d0f3c5
fix sample import & remove futures-util from dev dependencies
brodycj Feb 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tokio-stream/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ async-stream = "0.3"
parking_lot = "0.12.0"
tokio-test = { path = "../tokio-test" }
futures = { version = "0.3", default-features = false }
futures-test = "0.3.26"
futures-util = "0.3.26"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need these. We already import futures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that FutureExt is available from the futures crate.

Copy link
Contributor Author

@brodycj brodycj Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed futures-test. Unfortunately I still need futures-util to import FutureExt as I needed to get now_or_never() to work.

I noticed that tokio/src/sync/watch.rs is using recv.changed().now_or_never() from crate::sync::watch::channel(0i32) in some tests. I would like to investigate this a little further. Any pointers would still be highly appreciated as before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

futures::future::FutureExt worked for me thanks!


[package.metadata.docs.rs]
all-features = true
Expand Down
34 changes: 32 additions & 2 deletions tokio-stream/src/wrappers/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use tokio::sync::watch::error::RecvError;

/// A wrapper around [`tokio::sync::watch::Receiver`] that implements [`Stream`].
///
/// This stream will always start by yielding the current value when the WatchStream is polled,
/// regardless of whether it was the initial value or sent afterwards.
/// This stream will start by yielding the current value when the WatchStream is polled,
/// regardless of whether it was the initial value or sent afterwards,
/// unless you use [`WatchStream<T>::from_changes`].
///
/// # Examples
///
Expand Down Expand Up @@ -40,6 +41,28 @@ use tokio::sync::watch::error::RecvError;
/// let (tx, rx) = watch::channel("hello");
/// let mut rx = WatchStream::new(rx);
///
/// // existing rx output with "hello" is ignored here
///
/// tx.send("goodbye").unwrap();
/// assert_eq!(rx.next().await, Some("goodbye"));
/// # }
/// ```
///
/// Example with [`WatchStream<T>::from_changes`]:
///
/// ```
/// # #[tokio::main]
/// # async fn main() {
/// use futures_util::future::FutureExt;
/// use tokio::sync::watch;
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
///
/// let (tx, rx) = watch::channel("hello");
/// let mut rx = WatchStream::from_changes(rx);
///
/// // no output from rx is available at this point - let's check this:
/// assert!(rx.next().now_or_never().is_none());
///
/// tx.send("goodbye").unwrap();
/// assert_eq!(rx.next().await, Some("goodbye"));
/// # }
Expand All @@ -66,6 +89,13 @@ impl<T: 'static + Clone + Send + Sync> WatchStream<T> {
inner: ReusableBoxFuture::new(async move { (Ok(()), rx) }),
}
}

/// Create a new `WatchStream` that waits for the value to be changed.
pub fn from_changes(rx: Receiver<T>) -> Self {
Self {
inner: ReusableBoxFuture::new(make_future(rx)),
}
}
}

impl<T: Clone + 'static + Send + Sync> Stream for WatchStream<T> {
Expand Down
30 changes: 29 additions & 1 deletion tokio-stream/tests/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use tokio::sync::watch;
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt;
use tokio_test::assert_pending;
use tokio_test::task::spawn;

#[tokio::test]
async fn message_not_twice() {
async fn watch_stream_message_not_twice() {
let (tx, rx) = watch::channel("hello");

let mut counter = 0;
Expand All @@ -27,3 +29,29 @@ async fn message_not_twice() {
drop(tx);
task.await.unwrap();
}

#[tokio::test]
async fn watch_stream_from_rx() {
let (tx, rx) = watch::channel("hello");

let mut stream = WatchStream::from(rx);

assert_eq!(stream.next().await.unwrap(), "hello");

tx.send("bye").unwrap();

assert_eq!(stream.next().await.unwrap(), "bye");
}

#[tokio::test]
async fn watch_stream_from_changes() {
let (tx, rx) = watch::channel("hello");

let mut stream = WatchStream::from_changes(rx);

assert_pending!(spawn(&mut stream).poll_next());

tx.send("bye").unwrap();

assert_eq!(stream.next().await.unwrap(), "bye");
}