Re: [whatwg/fetch] Set body with byte reading support (PR #1593)

> I guess I should revise the sentence to also check whether the current byob request view is null and suspend the fetch if it is. Am I understanding correct?

Not really.

I guess there are two incompatible models in play here, and we have to pick a path.

1. Rely on buffering somewhere else in the stack. In this model, we'd:
   - Set highWaterMark = 0
   - Assume that as data comes in from the network, it's getting stored in a buffer/queue somewhere else in the stack, e.g. kernel, networking library, etc.
   - Wait for pulls. When we get a pull, either:
     - BYOB request is null, and so we create a new Uint8Array, grab whatever's in the other-part-of-the-stack buffer, put it into that Uint8Array, and enqueue it. (If nothing's there now, wait until something is.)
     - BYOB request is not null, and so we grab `byobRequestView.byteLength` bytes from the other-part-of-the-stack buffer, and write it into `byobRequestView`.
   - Write out some vague spec text about how we're assuming that stuff accumulating in the elsewhere-in-the-stack buffer causes backpressure, and thus will automatically suspend/resume bytes accumulating in that buffer, probably in a gradual fashion due to how TCP works.

2. Rely on the stream's internal queue. In this model, we'd basically do what your current draft of the PR does, or the current spec does. We only use enqueue, ignoring the current BYOB request. We'd use "suspend" and "resume" primitives to interface with the network layer, based on when the stream's internal queue is too full (i.e., when "need more data" is false).

There is no real observable difference between these for JavaScript developers. So maybe (2) is fine, perhaps supplemented with a note. But in terms of how they communicate strategies to implementers, (1) seems better. With (2), if you implemented it verbatim, you'd be doing (unobservable) copies all over the place, from the Uint8Arrays that have accumulated in the stream's internal queue via enqueue, into the BYOB request buffers the web developer supplies.

This is a bit more complicated because from what I understand, (1) is not really implementable directly on top of low-level OS socket APIs. This is because in that framing, the "buffer somewhere elsewhere in the stack" is the kernel buffer, and that has a limit, so you could eventually lose data if backpressure isn't respected fast enough. So really there's a hidden middle layer which wraps the OS socket APIs with an unlimited buffer, I think. But it's been many years since I investigated this and I'm not sure I ever fully understood it, so, I might not have that part correct...

((2) is definitely not implementable directly on top of low-level APIs, because there is no "suspend" or "resume" socket API. In some sense that is bad, but in some sense it's at least honest about how high-level it is.)

Anyway, I think thoughts from implementers on what would be the most helpful would be appreciated. /cc @ricea 

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/fetch/pull/1593#issuecomment-1381485320
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/fetch/pull/1593/c1381485320@github.com>

Received on Friday, 13 January 2023 08:42:21 UTC