Skip to content

Transform streams and acknowledgement of writes #329

Open
@domenic

Description

@domenic

Spinning off from roughly yutakahirano/fetch-with-streams#30 (comment), I think we want to take a more general look at how we envision transform streams working.

Here is some code for reference:

const ts = TransformStream.identity({ highWaterMark: 0 }); // speculative API

ts.writable.write("foo").then(onWritten, onWriteFailed);

setTimeout(() => {
  ts.readable.getReader().read().then(({ value, done }) => {
    // (1)
    return doSomethingAsyncWith(value);
  });
}, 1000);

In the current design, onWritten will always be called ASAP, whereas onWriteFailed will never happen. (In the more general transform stream case, onWritten will be called when the possibly-async transformation finishes, while onWriteFailed will be called if it fails.) The current design is based on how Node.js/io.js handles things.

In the linked thread, @wanderview proposes (indirectly) a design where onWritten is called only after the chunk leaves the transform stream to head for the readable stream (i.e. after 1 second, roughly around the same time as (1)). In this design onWriteFailed is also never called.

@tyoshino's read-acknowledgment proposal (#324 and previous) would allow for a third design, where onWritten would be called once doSomethingAsyncWith(value) succeeds, and onWriteFailed would be called if it fails. This would require a slight modification to the above, e.g. something like

ts.readable.getReader({ requireAcks: true }).read().then(({ value, done, waitUntil }) => {
  waitUntil(doSomethingAsyncWith(value));
});

which could be a burden on the consumer to remember to use.


There's two aspects to keep in mind with these proposals:

  • How well they propagate write success/failure
  • How well they propagate backpressure

I think all can propagate backpressure pretty well, with minor tricks. But propagating write success/failure all the way from the ultimate sink to the original producer is only really possible with #324, I think. (Except perhaps through things like #325 which could help with special cases...)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions