-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Make streams owned by request/response that they are tied to. #6228
Conversation
cc @pchickey |
fwiw, looks like tests failed b/c of a network failure pulling the |
I hit rerun and now it got to a test failure |
I'm going to move this to @pchickey's review queue as he's more familiar with the implementation than I |
crates/wasi-http/src/types_impl.rs
Outdated
@@ -123,7 +123,13 @@ impl crate::types::Host for WasiHttp { | |||
bail!("unimplemented: drop_incoming_request") | |||
} | |||
fn drop_outgoing_request(&mut self, request: OutgoingRequest) -> wasmtime::Result<()> { | |||
self.requests.remove(&request); | |||
match self.requests.get(&request) { |
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.
nit; since we only care about the Some
case, how about an if let Some(r) = self.requests.get(&request)
instead?
Or even
if let Entry::Occupied(e) = self.requests.entry(request) {
let r = e.remove();
https://doc.rust-lang.org/std/collections/hash_map/struct.OccupiedEntry.html#method.remove
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.
Done.
Thanks for the suggestion, I'm still learning idiomatic rust)
crates/wasi-http/src/struct.rs
Outdated
@@ -2,6 +2,12 @@ use crate::types::{Method, Scheme}; | |||
use bytes::Bytes; | |||
use std::collections::HashMap; | |||
|
|||
#[derive(Clone)] |
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.
How about a derive(Default)
?
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.
done.
@@ -66,6 +72,15 @@ impl ActiveResponse { | |||
} | |||
} | |||
|
|||
impl Stream { | |||
pub fn new() -> Self { | |||
Self { |
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.
If we had a Default
trait impl, this could have just called Self::default()
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.
done.
let st = self | ||
.streams | ||
.get_mut(&stream) | ||
.ok_or_else(|| anyhow!("stream not found: {stream}"))?; |
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.
Doesn't with_context
work here?
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'm not sure I'm following your suggestion, can you clarify?
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.
Sure, I'm referring to this method on the anyhow::Context
trait https://docs.rs/anyhow/latest/anyhow/trait.Context.html#tymethod.with_context
If it's in scope, you should be able to call context
or with_context
(usually used with format!
and similar) on most Result
and all Option
types directly, thus eliminating the need for ok_or_else
and explicit anyhow!
invocation
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.
@rvolosatovs I made those ok_or_else(|| anyhow!(...)) suggestions in a prior PR and wasn't aware that Context could make that more succinct. Thank you.
@brendandburns The suggested change here is let st = self.streams.get_mut(&stream).with_context(|| format!("stream not found: {stream}"))?;
, or maybe even ....get_mut(&stream).context("stream not found")?
if leaving out the stream number is ok - and it probably is, because (at least when using the component linker, I'm not sure if it works in module mode) bindgen is inserting tracing
statements which someone debugging can recover the values of the arguments from.
crates/wasi-http/src/streams_impl.rs
Outdated
this, | ||
Stream { | ||
closed: false, | ||
data: bytes::Bytes::from(buf.clone()), |
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.
You wouldn't need this clone if the call to buf.len
below was moved higher, before the match.
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.
done.
crates/wasi-http/src/http_impl.rs
Outdated
@@ -183,7 +183,8 @@ impl WasiHttp { | |||
let body = Full::<Bytes>::new( | |||
self.streams | |||
.get(&request.body) | |||
.unwrap_or(&Bytes::new()) | |||
.unwrap_or(&Stream::new()) |
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.
If we had Default
implemented, this could have been unwrap_or_default
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.
Unfortunately, HashMap::get(...)
returns a reference rather than a value, and there's no default for a reference. I could implement the Default
trait for &Stream
references, but I'm not sure if that's what is best. Let me know.
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.
That makes sense, I think this is fine.
I am making a few changes here to allow for the host to provide a custom connect implementation, so I'll take a deeper look at this as well next week
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.
@@ -2,6 +2,12 @@ use crate::types::{Method, Scheme}; | |||
use bytes::Bytes; | |||
use std::collections::HashMap; | |||
|
|||
#[derive(Clone)] | |||
pub struct Stream { |
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.
Looking at the usages of this struct, it seems that a From<Bytes>
implementation could really clear this up
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.
added.
crates/wasi-http/src/streams_impl.rs
Outdated
self.streams.insert(this, new.freeze()); | ||
self.streams.insert( | ||
this, | ||
Stream { |
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.
If there was a From
implementation, this could have been Stream::from(new.freeze())
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.
done.
Comments generally addressed, couple where I need some more feedback. Please take another look. Thanks! |
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.
Just a general question, why are we not modifying the stream data buffer, but rather cloning it? In other words, why would we ever want to read the same bytes more than once?
crates/wasi-http/src/http_impl.rs
Outdated
self.streams.insert(response.body, buf.freeze()); | ||
self.streams.insert( | ||
response.body, | ||
Stream { |
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.
This should probably also use the From
trait
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.
done.
I'm not sure I follow your question. Are you asking why we don't use Let me know if that's the change you are suggesting, or if I'm missing something. Thanks! |
@brendandburns I can merge this when ready, please ping when the above discussion is resolved. |
crates/wasi-http/src/streams_impl.rs
Outdated
bail!("stream is dropped!"); | ||
} | ||
let new_len = st.data.len() + len; | ||
let mut new = bytes::BytesMut::with_capacity(new_len); |
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.
From #6228 (comment), as you said, I think I'd just use BytesMut
and https://docs.rs/bytes/latest/bytes/struct.BytesMut.html#method.extend_from_slice here
Since that would be quite a bit shorter, it could probably also make sense to remove the match altogether and instead rely on https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.and_modify (see example there with or_insert
)
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.
Done. I needed to use .or_default().extend_from_slice(...)
but I think it achieves the same goal (and thanks for the suggestion of implementing Default
that made it possible :)
@pchickey I think this is ready to merge. |
…dealliance#6228) * Make streams owned by request/response that they are tied to. * Address comments, fix tests. * Address comment. * Update crates/wasi-http/src/streams_impl.rs Co-authored-by: Pat Hickey <[email protected]> * Switch to BytesMut --------- Co-authored-by: Pat Hickey <[email protected]>
…dealliance#6228) * Make streams owned by request/response that they are tied to. * Address comments, fix tests. * Address comment. * Update crates/wasi-http/src/streams_impl.rs Co-authored-by: Pat Hickey <[email protected]> * Switch to BytesMut --------- Co-authored-by: Pat Hickey <[email protected]>
This is related to the discussion here: WebAssembly/wasi-http#24
Where we decided that streams should be
child-own
properties of the request or response that they are tied to.This adds clarity to when it is valid to drop an input or output stream and in what order relative to the response.