Re: [whatwg/streams] Reset for TransformStream (and WritableStream?) (#1026)

Until now, what we've been doing is to abort the pipe and then re-create it with a new source:
```javascript
const controller = new AbortController();
const sink = new WritableStream({ ... });
let currentPipe = Promise.resolve();

async function setSource(source) {
  controller.abort();
  controller = new AbortController();
  await currentPipe; // wait for the sink to become unlocked
  currentPipe = source
    .pipeThrough(transform())
    .pipeTo(sink, { signal: controller.signal, preventAbort: true })
    .catch(() => {});
}
```
This will properly discard any queued chunks. However, we need to re-create all transform streams between the `source` and `sink`, which is quite annoying.

A `reset()` method could help to avoid re-creating those transform streams. However, as you already pointed out, the semantics can get tricky.

---

> This would have unusual semantics that it could be called while a transform is in progress.

If a `transform()` is already in progress, then we need to wait for it to complete before we can clear the queues. Otherwise, the pending `transform()` may asynchronously enqueue chunks after the `reset()` call, which were derived from chunks from before the `reset()` call.

Perhaps it could help to make `pull()`, `transform()` and `write()` take an `AbortSignal`, as [I suggested previously in #1014](https://github.com/whatwg/streams/issues/1014#issuecomment-531244783)? With that, the steps for `TransformStream.reset()` could look like:
1. If a `transformer.transform()` is in progress, abort its `AbortSignal`.
1. Wait for the in-progress `transform()` promise to complete.
1. Call `transformer.reset()`.

---

Still, all of this relies on the transformer actually implementing the `reset()` method. What if it doesn't? We have no way of knowing what sort of internal state the transformer is keeping on any chunks it has previously (partially) transformed. As such, we don't know whether the transformer will be ready to receive a completely new chunk (which isn't a continuation from the previous old chunk) in its next `transform()` call.

Does that mean that you can only reset a transform stream that actually implements `reset()`? But how would that work in a long pipe chain, where some transforms do implement it and others don't? You might have already reset a bunch of transform streams before you encounter one that doesn't support it. Now, half of the pipe has had its queue cleared and expecting new chunks, while the other half is still processing old chunks and expecting a continuation of those old chunks. This would seriously mess up the whole chain!

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1026#issuecomment-580942977

Received on Friday, 31 January 2020 22:41:51 UTC