Skip to content
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

fix stream.js to allow pausing when there are many blocks #24

Merged
merged 2 commits into from Feb 19, 2021

Conversation

staltz
Copy link
Member

@staltz staltz commented Feb 18, 2021

1st test, 2nd fix

IF the stream has many blocks AND the sink pauses frequently, THEN the previous implementation has a bug where it gets stuck at the last record, giving this last record over and over to the sink, in a loop.

The culprit was that _handleBlock needs 3 different return values, we can't signal "pause" on neither true nor false (I tried many times, all sorts of tricks).

@staltz staltz requested a review from arj03 February 18, 2021 23:26
@staltz staltz changed the title add tests for pausable multi-block stream fix stream.js to allow pausing when there are many blocks Feb 18, 2021
@arj03
Copy link
Member

arj03 commented Feb 19, 2021

Will review this one now :)

@@ -149,8 +152,10 @@ Stream.prototype.abort = function (err) {
this.ended = err || true
var i = this.blocks.streams.indexOf(this)
if (~i) this.blocks.streams.splice(i, 1)
if (!this.sink.ended && this.sink.end)
if (!this.sink.ended && this.sink.end) {
this.sink.ended = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a nice catch

Stream.prototype._handleBlock = function(block) {
while (true) {
if (this.sink.paused) return false
if (this.sink.paused) return null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering why exactly this is different from what it was before? I mean after was a this.sink.paused check instead of the null check, so was the a concurrency bug where the value of this.sink.paused was changed between the return and the else if check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was so tricky, and it was so late at night, that I can't quite remember the reason. Wanna try changing it to false and seeing what happens?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll try that :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting it didn't work before. Wow tricky bug!

else if (this.sink.end)
return this.sink.end(this.ended === true ? null : this.ended)
}
return
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm yes, this looks more correct

@staltz staltz merged commit 1bbde1d into master Feb 19, 2021
@arj03
Copy link
Member

arj03 commented Feb 19, 2021

Nice work on this one. The module wasn't at all tested for the pause so no wonder you run into a few of those. It's really tricky business implementing that correctly.

@staltz
Copy link
Member Author

staltz commented Feb 19, 2021

Yep! I'm also curious if this will improve some things elsewhere. Like, the new test would basically end up in an infinite loop with the old implementation. Maybe this infinite loop was happening elsewhere and slowing things down? (Well not just slowing, but deadlocking them)

@staltz staltz deleted the pausable-again branch February 19, 2021 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants