Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Async Series hangs in then block, but runs fine when called directly. #1069

Closed
sjkelleyjr opened this issue Nov 12, 2017 · 5 comments
Closed
Labels
kind/support A question or request for support

Comments

@sjkelleyjr
Copy link

Version: 0.26.0
Platform: Linux 4.4.0-98-generic #121-Ubuntu SMP Tue Oct 10 14:24:03 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Subsystem: Files

Type: Bug

Severity: High

Description:

I'm able to call the below writeUserMetrics function directly with an address string and some JSON. When I do this, the async series funcitons as expected and I get the JSON printed to the console. However, since the address is dependent externally (can't be hard coded) I make a call to retrieve this address, and then pass it into the same method call that works when called directly. This time, the function call hangs and fails to output anything. If I try to print the fileMultihash variable during this hanging, I get no output whatsoever.

Steps to reproduce the error:

Call the series directly, then call it in the context of a then block from another async call returning. The then block call will hang.

CODE SNIPPETS

uport.requestCredentials({},
    uri => qrcode.generate(uri,{small:true}))
    .then(userProfile => {
      ipfsNode.writeUserMetrics(userProfile.address,{numberOfDefaults:0, openLoans:5, LoansPaidBack:15});
    })
const createJSONBuffer = (UsersFinancialMetrics) => {
  return Buffer.from(JSON.stringify(UsersFinancialMetrics));
};
exports.writeUserMetrics = async (uPortAddress, userJSON) => {
  let fileMultihash;
  series([
    (cb) => node.on('ready', cb),
    (cb) => node.version((err, version) => {
     if (err) { return cb(err) }
     console.log('Version:', version.version)
      cb()
    }),
    (cb) => node.files.add({
      path: uPortAddress,
      content: createJSONBuffer(userJSON)
    }, (err, result) => {
      if (err) {
        return cb(err) 
      }
      fileMultihash = result[0].hash
      cb()
    }),
    (cb) => node.files.cat(fileMultihash, (err, stream) => {
      if (err) { return cb(err) }
      stream.pipe(process.stdout)
    })
  ])
} 

Any ideas?

@richardschneider
Copy link
Contributor

In the final series, the cb is never being called to indicate the the piping is done.

(cb) => node.files.cat(fileMultihash, (err, stream) => {
      if (err) { return cb(err) }
      stream.pipe(process.stdout)
    })

This is most likely stuffing up the pipe line.

Try replacing it with the following, for debugging purposes

(cb) => {
  console.log('done);
  cb();
}

@sjkelleyjr
Copy link
Author

sjkelleyjr commented Nov 12, 2017

Thanks for the response. Tried it, didn't work.

The problem is, it isn't even getting to that final callback. If I try and console log result in the callback above that, I get nothing, so I don't think it's a stdout buffer problem. I don't think the file is even being added.

I tried altering the object in the then call (adding a timestamp). I then go to the URL and the JSON object remains unchanged, so it really isn't adding the file at all.

Now that I think of it, node.on('ready') isn't being trigger inside the then call, but it is outside. Any reason this might be the case? I tried to see if there is any networking happening in the other library but nothing shows up in the lsof -i command. Also, tried catching any kind of exception in the async-series calls, nothing came out.

@daviddias
Copy link
Member

The issue is coming from wrapping the node.on('ready') on the series sequence. That event comes from an event emitter which means that it won't be waiting for listeners (like a Readable Stream) to get emitted. Since you are adding the node.on('ready') way after you create a node, some async operations already happened and the node is already started, not emitting the same event twice.

@daviddias daviddias added the kind/support A question or request for support label Dec 4, 2017
@sjkelleyjr
Copy link
Author

That was it, all I had to do was remove the node.on('ready') call in the series sequence and everything worked as expected. Thank you!

Any chance something like this could get added to the documentation to clarify that the node.on('ready') call doesn't necessarily need to be made every time?

@daviddias
Copy link
Member

Good to hear @sjkelleyjr!

Any chance something like this could get added to the documentation to clarify that the node.on('ready') call doesn't necessarily need to be made every time?

We use straight up the Event Emitter pattern. You can find docs of the implementation used (most widely used) at the Node.js docs https://nodejs.org/api/events.html Hope this helps.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/support A question or request for support
Projects
None yet
Development

No branches or pull requests

3 participants