- From: Domenic Denicola <notifications@github.com>
- Date: Thu, 15 Jan 2015 12:32:28 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Message-ID: <whatwg/streams/issues/263@github.com>
This is mostly for discussion, as it is probably not a bug problem. But I wanted to lay it out.
In the review of some reader fixes at https://github.com/whatwg/streams/pull/262#discussion_r22993414 @yukatahirano pointed what you could see as a potential waiting -> waiting transition. It occurs even without readers so I think we can leave them out of the discussion. An example:
```js
stream.ready.then(() => console.log(stream.state));
// enqueue a chunk
stream.read();
// will log "waiting"
```
Normally we try to enforce that when `ready` fulfills, the state is no longer `"waiting"`, since kind of the point of `ready` is to tell you when you're done waiting.
This kind of usage is atypical though so it is not too problematic. Usually you do not know, until `ready` fulfills, that the stream has become `"readable"`. In this example we are using external knowledge---namely, the fact that on the previous line we enqueued in the stream---to figure it out.
If we were to think about mitigating this, the options don't seem great:
- Delay fulfilling `ready` for a microtask; at that time check if state is now `"waiting"` (due to queue drainage) and if so don't fulfill `ready`. This kind of just shuffles the problem around though: someone could just do `Promise.resolve().then(() => stream.read())` to "fool" the check by waiting until after it happens.
- Make everything async: i.e., don't actually do the enqueue until a microtask later. So if you enqueue, the chunk will not be immediately available for `read()`. We should be able to schedule the availability of the chunk such that it happens immediately before `ready` fulfills, thus avoiding any possibility of interleaving as in the above possibility.
- Embrace sync instead of async: stop using promises and use some sort of [zalgo-esque](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) callback system that synchronously notifies of availability. I am not sure why I am even mentioning this.
I just realized there is another way to encounter a `"waiting"` state in the `ready` handler, even when doing "normal" usage:
```js
stream.ready.then(() => {
console.log(stream.state);
stream.read();
});
// in some other part of the code, perhaps:
stream.ready.then(() => {
console.log(stream.state);
});
// enqueue a single chunk
// will log "readable", "waiting"
```
basically any multi-consumer scenario has the potential to see "waiting".
So in general maybe the takeaway here is to add a quick note that usually the state will be non-"waiting", but it's possible that it will be "waiting" if someone drained the queue between the transition happening and your fulfillment handler being called. I still think it's worthwhile to preserve the pseudo-invariant in other cases though.
---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/263
Received on Thursday, 15 January 2015 20:33:03 UTC