-
Notifications
You must be signed in to change notification settings - Fork 311
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
Backpressure on fetch integrated with Streams #452
Comments
I'm not sure this is the right place to discuss this issue, but I chose here because it could affect the fetch interface. |
It would be good to get input from @domenic. Note that I expect we would not expose a |
To explain @annevk's comment a bit more, I believe our thinking was that (Conceptually, My expectation would then be that upon The choice of HWM could in theory be given to users (e.g. as an option to /cc @tyoshino in case there's something I am forgetting |
@domenic |
Thank you. My understanding is the following - Are those right?
|
Yeah, although I'm not sure if we can make the third bullet point work if we keep the stream object pure. Perhaps through some temporary observer? But even that would have to be synchronous for |
The third bullet point is definitely achievable since we'd control the creation of the stream. E.g. var that = this;
this.body = new ReadableByteStream({
readInto(/* ... */) {
// actual work
that.bodyUsed = true;
}
}); |
min? The proposed back pressure mechanism looks correct. Regardless of where
I agree that it works. To simplify implementation, we would want to use But even if we adopt this approach, it seems we can still choose to determine the body reading method to provide to the user at access on body property. Not on
Unless we want to allow the user to investigate body before deciding what body reading method to use. I guess there's no such need. |
Fixed to return the Objects implementing the Body ... an associated byteStream (initially set to null), ...
|
@tyoshino I guess that could work, but perhaps we should make it a method then given all the side effects. But instead of returning a promise it would be synchronous. Not sure though. |
@annevk Sounds good |
I don't really like the side-effecting method. I'd rather just go with the approach from #452 (comment). It also makes the name |
@yutakahirano because it's more complex (both in internal code and user-facing code/concepts) than #452 (comment) and doesn't gain anything. |
I see. In your idea, |
Nah, if you do that you'll get what you asked for. (A mess.) |
Right. To choose not to do that, I want to give a justification supporting that we're putting a guard against @yutakahirano said that it might be useful to keep Regarding guard against |
We don't really have any concept of "exclusive access to a stream." If you have a stream object, you can read from it; this is similar to a file handle object. it would be possible to introduce a library or subclass that adds this concept, but I would prefer to let libraries prove the worth of that idea and if we see everyone building such tooling them consider standardizing it. .cancel() is indeed a good reason to keep ReadableStream methods available. That said, this kind of situation where a "C++ reader" and a "JS reader" might share a stream seems very reminiscent of the off-main-thread piping question, whatwg/streams#97. In fact you can view it as a subset of that if you define Response.prototype.json = function () {
var concatenator = new ConcatStream();
this.body.pipeTo(concatenator);
return concatenator.asArrayBuffer.then(convertToString).then(JSON.parse);
}; (npm concat-stream is for Node streams and uses a callback; our hypothetical version uses a promise-returning I will open a new issue on whatwg/streams and consider if maybe we want to lock the stream during piping. |
By "exclusive", I meant exclusive between My idea in #452 (comment) realizes this by hiding the stream object itself when
OK
Good |
It seems that whatwg/streams#241 allows "read-and-then-pipeTo", but you don't want to allow "read-and-then-call-json" in this issue, right? With stream() method, we can solve the problem, though. |
We definitely want to allow read and then call json(), e.g. for a file format that has descriptive headers then JSON content |
Yeah, it's useful. But now there's no way to tell the stream how big the header is. Using |
Oh, sorry, I mistook your intention, but it is a bit different from what I said at #452 (comment) . And for your use case, we need read(size) which we don't have now. |
You would use readInto, yes. Not sure about the utility of json(num_bytes). In my view json() is just a stopgap until we have real streams, and/or a convenience for the 80% case. |
What is "readInto"? Is it part of the Streams API? |
I got some offline comment about politically incorrectness of naming. I've renamed it to "body passed". |
Copied #452 (comment) to |
Sorry. (A)' was not depicting Domenic's #452 (comment). Added (A)'' which should be depicting it more correctly. |
BTW, Yutaka questioned what we should do with the ReadableStream when e.g.
|
I agree with this.
(A)'' depicts my idea.
I think 1 or 2 are reasonable and I don't have a strong preference between them. 1 would be text() doing nothing, and 2 would be text() calling |
utf-8 would not suddenly fail to decode if you hit a trailing byte. You would just get a U+FFFD. I don't think we want to use a fatal decoder. |
OK. So, |
I'm not sure how multipart/form-data is normally processed. I guess we don't parse it ourselves normally so making it a fatal error is fine if we keep doing that consistently. |
Just a nitpick, but you don't have to have an entry for |
Yutaka: Thanks. Done tyoshino/streams_integration@723bb07 |
Thanks, Anne, Domenic. Let's have Re: Domenic (#452 (comment)), OK. Let's proceed with that plan. I've moved (A)'' to the top in https://github.com/tyoshino/streams_integration/blob/master/FetchBodyPrecondition.md. |
Except |
Yes. As you said, |
s/never fails/never fails as long as body doesn't become `"errored"/ |
Thank you @tyoshino and others, I will update the draft. |
What is the type of the "chunk" provided by Fetch body ReadableStream objects? Is it an ArrayBuffer? The streams spec says a chunk can be of any type, but we should probably define what Fetch body streams return explicitly. (Sorry if this is already defined and I missed it. Its a bit hard to follow the overall effort.) |
Yes, |
Used 'passed flag' instead of 'used flag' as discussed at w3c/ServiceWorker#452.
Used 'passed flag' instead of 'used flag' as discussed at w3c/ServiceWorker#452.
Hi! Sorry that it took so long, but I updated the draft. |
I suggest any further review is done in that repository until the merge happens (at which point we should switch to https://github.com/whatwg/fetch I think for anything new). |
Imagine ReadaleStream is integrated with fetch. The most naive way is to add stream() method to Body interface.
Streams is an API that enables the data producer to know that the consumer doesn't want the data and stop producing data. On the other hand, other data types (text, blob, ...) don't have such feature.
My question is, should the loader start loading body while the Body representation is undetermined?
The above code waits longtime and then demonstrates that it wants to get the body data via ReadableStream interface. Should the loader load the body data while waiting and use the internal buffer unlimitedly, or stop loading while the representation is undetermined?
We can provide that information explicitly when calling fetch, but I don't know if it's a good API.
The text was updated successfully, but these errors were encountered: