-
Notifications
You must be signed in to change notification settings - Fork 154
Provides an EventSource implementation #246
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
Conversation
29b49ae
to
ee52f7c
Compare
Modelled on the WebSocket API.
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.
For the maintainers of this repository: I am the original author of SSE support in Akka HTTP (see https://github.com/hseeberger/akka-sse) and have been working with Rust in production for some years, also created some OSS libraries (e.g. https://crates.io/crates/pub-sub-client).
Thanks Chris for this excellent PR. I only have some minor suggestions and I'd love to see this being merged.
@@ -37,7 +38,7 @@ wasm-bindgen-test = "0.3" | |||
futures = "0.3" | |||
|
|||
[features] | |||
default = ["json", "websocket", "http"] | |||
default = ["json", "websocket", "http", "eventsource"] |
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.
Generally I am reluctant to putting "too" many features into the default one, but as we already have websocket here I guess we can also have eventsource.
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, seemed to make sense to continue following the convention.
crates/net/README.md
Outdated
@@ -19,7 +19,7 @@ | |||
<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub> | |||
</div> | |||
|
|||
HTTP requests library for WASM Apps. It provides idiomatic Rust bindings for the `web_sys` `fetch` and `WebSocket` API | |||
HTTP requests library for WASM Apps. It provides idiomatic Rust bindings for the `web_sys` `EventSource`, `fetch` and `WebSocket` APIs. |
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.
Maybe reorder "fetch , EventSource" to sort by specificy/power.
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.
When in doubt, I put things in alphabetical order. Happy to reorder here though.
/// events without an event field as well as events that have the | ||
/// specific type `event: message`. It will not trigger on any | ||
/// other event type. | ||
pub fn subscribe_event(&mut self, event_type: &str) -> Result<(), JsError> { |
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 suggest to rename this function to just subscribe
. And the same for unsubscribe
below. It's obvious that we are dealing with events and there is nothing else to subsrcibe to.
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.
Will do
Commit 1ea4f0a addresses @hseeberger's feedback. Thanks for the review, Heiko! |
Unsure why the browser tests are failing on CI. Doesn't appear related. |
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.
Why not use gloo_events::EventListener
instead of manually registering callbacks?
Also. I'm not sure if this is the best way to expose the API. What if someone wants to subscribe to different events at different places? I would prefer if each subscribe method would return a EventSubscription
that can be consumed independently of the EventSource
. Of course, this causes complications with closing the underlying web_sys::EventSource
. One solution I can think of is to close the connection when all the EventSubscription
s are dropped. A method to forcefully close the connection can also be provided but with a warning that there may be EventSubscription
s that are still using this connection. Waiting on them will lead to a deadlock
pub struct EventSource { ... }
impl EventSource {
fn new(...) -> Self;
fn subscribe_event(&self, event: &str) -> EventSubscription;
fn subscribe_all(&self) -> EventSubscription { self.subscribe_event("message") }
}
struct EventSubscription { ... }
impl EventSubscription {
// This is our event source. It can Rc'd to be passed around
fn event_source(&self) -> &EventSource { ... }
}
impl Stream for EventSubscription { ... }
impl Drop for EventSubscription { unsubscribe the event }
I'm unsure what the stringified event names should be when registering in a more generic way. I think it might be How we actually register the event types is an implementation detail though. Would you mind if we defer to an improved method in a subsequent PR if you feel it would benefit the code?
I think having a stream per subscription adds a bit of complexity, so I'm not sure it is a great idea. In my experience with SSE, I've found that I typically consume all events in one place. However, I appreciate that what you're suggesting is perhaps more in line with the underlying API. Do we really want multiple streams being driven and consumed though? Again, I'm not convinced that the complexity is worth it. Also, I don't believe there's a way of subscribing to all events. There's an on_message event handler, but I believe that it only fires when there is no event type specified in the source data. If you subscribe to |
I had to scratch this itch to see how it looks. I'm actually quite happy with it and have now pushed a commit that implements what you suggested. The commit is fa096f3. |
I'm going to revert this back to a draft for now while I get the subscription stream approach working. I'm really unsure about the tests running properly also, so I want to delve into that a bit more. |
OK, this is ready for review again. I've checked that it continues to work given another app. I'm unhappy that I'm not able to get the tests running locally - well, they run, but I can't seem to get them to fail. I'm also not convinced that the CI issue being reported is related. Other than that, I'm happy with the approach taken here given the fabulous feedback received. |
I had previously assumed that the event source would fire an error event on close, but it only does it on open according to the docs. We therefore fire the error event explicitly so that the subscribed streams know when to shut down.
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.
Sorry, it took me so long to review this. I've been busy with work and real life stuff.
I'll address the review comments myself and merge it
Will do thiserror eventually … |
No problem at all! Thanks to you and @hseeberger for the excellent reviews. Hope real life stuff is ok with you. |
Inspired by the WebSocket API.
Example usage:
TODO:
Fixes ranile/reqwasm#8
Fixes #8