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

propagation of _.nil in async scenario #173

Closed
jeromew opened this issue Nov 27, 2014 · 2 comments
Closed

propagation of _.nil in async scenario #173

jeromew opened this issue Nov 27, 2014 · 2 comments
Assignees

Comments

@jeromew
Copy link
Collaborator

jeromew commented Nov 27, 2014

Hello,

I had a 'freeze' bug in a complex pipeline that I managed to simplify to the following.

var _ = require('./lib/index.js');
_([1])
.consume(function(err, x, push, next) {
  if (err !== null) {
    push(err);
    next();
  }
  else if (x === _.nil) {
    console.log('first nil')
    setImmediate(function() {
      push(null, x);
    })
  }
  else {
    push(null, x);
    next();
  }
})
.consume(function(err, x, push, next) {
  if (err !== null) {
    push(err);
    next();
  }
  else if (x === _.nil) {
    console.log('second nil')
    push(null, x);
  }
  else {
    push(null, x);
    next();
  }
})
.resume();

I had the impression that this should log first nil and second nil (which it does in the sync case) but by forwarding the _.nil in an async fashion with setImmediate as a test, only first nil is logged.

Am I missing something ?

I noticed that if I call next() in the async case, then it starts working again so I concluded that there is either a bug or something that I don't understand about calling next() in the _.nil case

@vqvu
Copy link
Collaborator

vqvu commented Nov 27, 2014

If you call resume() again, you'll see the second nil. It's because the consume stream will pause if you don't synchronously call next. Thus, when you finally push the nil, you're pushing onto a paused stream, and it gets buffered instead of emitted downstream. Normally this is OK, since next will be called after the push if you need to do an async push (and next will resume the stream), but this isn't the case when pushing nil.

It's definitely a bug not to resume the stream after an async nil. It's not trivial to fix though. The reason for the pause is to guard against upstream producers that don't call next in between two push, but it's not the correct thing to do.

Here's another, related, bug with consume.

var s = _([1, 2])
.consume(function(err, x, push, next) {
  if (err !== null) {
    push(err);
    next();
  }
  else if (x === _.nil) {
    push(null, x);
  }
  else {
    if (x === 1) {
      setImmediate(function () {
        push(null, x);
        next();
      });
    } else {
      push(null, x);
      next();
    }
  }
})

s.toArray(_.log);
// => [2, 1]

I'll take ownership of this, since what I'm working on for #41 is related.

@vqvu vqvu self-assigned this Nov 27, 2014
@vqvu
Copy link
Collaborator

vqvu commented Nov 29, 2014

Actually, what I mentioned is not a bug. It doesn't happen. I seemed to be working with the wrong branch.

@vqvu vqvu closed this as completed Nov 29, 2014
@vqvu vqvu reopened this Nov 29, 2014
vqvu added a commit to vqvu/highland that referenced this issue Nov 29, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - caolan#41
  - caolan#141
  - caolan#142
  - caolan#173
vqvu added a commit to vqvu/highland that referenced this issue Nov 29, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - caolan#41
  - caolan#141
  - caolan#142
  - caolan#173
vqvu added a commit to vqvu/highland that referenced this issue Nov 29, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - caolan#41
  - caolan#141
  - caolan#142
  - caolan#173
vqvu added a commit to vqvu/highland that referenced this issue Nov 29, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - caolan#41
  - caolan#141
  - caolan#142
  - caolan#173
vqvu added a commit to vqvu/highland that referenced this issue Nov 29, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - caolan#41
  - caolan#141
  - caolan#142
  - caolan#173
vqvu added a commit that referenced this issue Dec 13, 2014
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - #41
  - #141
  - #142
  - #173
vqvu added a commit that referenced this issue Jan 25, 2015
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - #41
  - #141
  - #142
  - #173
vqvu added a commit that referenced this issue Jan 25, 2015
This involves:
  - Totally reimplementing stream redirection.
  - Reimplementing `consume`, `pull`, `fork`, and `resume`.

Backward incompatible;
  - The stream no longer pauses if `next` isn't synchronously called
    in
    `consume`, since this is no longer necessary to signal (lack of)
    demand to the source.
  - Lots of methods and properties that start with `_` changed
    (these
    were private anyway).
  - The callback for the stream generator and `consume` is
    guaranteed
    not to be called a second time until `next` is called.

Fixes:
  - #41
  - #141
  - #142
  - #173
@vqvu vqvu closed this as completed in f23493f Feb 11, 2015
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

No branches or pull requests

2 participants