-
Notifications
You must be signed in to change notification settings - Fork 5
Implement stream listener #20
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
Changes from 16 commits
da0dacd
c15cd54
cfca334
4e3db7f
de32666
6bfb8a1
7a6f79a
4d49882
5138e09
04222ae
51ecbb2
0a78b64
835bf08
0c24840
541cc1e
2950644
376deda
6f7a305
702e4df
2bed000
ce77a36
2dc4cc1
2638334
bbabca9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| rust 1.85.1 | ||
| rust 1.88.0 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| use crate::tasks::{GenServer, GenServerHandle}; | ||
| use futures::{Stream, StreamExt}; | ||
| use spawned_rt::tasks::{CancellationToken, JoinHandle}; | ||
|
|
||
| /// Spawns a listener that listens to a stream and sends messages to a GenServer. | ||
| /// | ||
| /// Items sent through the stream are required to be wrapped in a Result type. | ||
| /// | ||
| /// This function returns a handle to the spawned task and a cancellation token | ||
| /// to stop it. | ||
| pub fn spawn_listener<T, F, S, I, E>( | ||
| mut handle: GenServerHandle<T>, | ||
| message_builder: F, | ||
| mut stream: S, | ||
| ) -> (JoinHandle<()>, CancellationToken) | ||
| where | ||
| T: GenServer + 'static, | ||
| F: Fn(I) -> T::CastMsg + Send + 'static, | ||
| I: Send, | ||
| E: std::fmt::Debug + Send, | ||
| S: Unpin + Send + Stream<Item = Result<I, E>> + 'static, | ||
| { | ||
| let cancelation_token = CancellationToken::new(); | ||
| let cloned_token = cancelation_token.clone(); | ||
| let join_handle = spawned_rt::tasks::spawn(async move { | ||
| loop { | ||
| if cloned_token.is_cancelled() { | ||
|
||
| tracing::trace!("Received signal to stop listener, stopping"); | ||
| break; | ||
| } | ||
|
|
||
| match stream.next().await { | ||
| Some(res) => match res { | ||
| Ok(i) => { | ||
| let _ = handle.cast(message_builder(i)).await; | ||
| } | ||
| Err(e) => { | ||
| tracing::trace!("Received Error in msg {e:?}"); | ||
| break; | ||
| } | ||
| }, | ||
| None => { | ||
| tracing::trace!("Stream finished"); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| (join_handle, cancelation_token) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the idea of creating the
CancellationTokenin theGenServeron initialization. And every time a listener or a timer is spawned to interact with theGenServerit should request it for theCancellationTokento reuse the same one.Then, it's the
GenServerresponsibility to cancel the token on termination. That way, graceful cancellation is transparent for the external process.Anyway, we can try to implement that on this PR, or ticket it for a future improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it'd be a good idea to have the cancellation token inside of the gen server, considering this change would also requiere a change in the
timerimplementation, I believe we should make this change on a separate PR.I'll branch from this one and start work on it ASAP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, given GenServer is just a Trait, I guess we should put the token in the GenServerHandler, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I've taken an approach of that kind, see the PR here