0

I'm new to Node.js and asynchronous calls, but I'm trying to build a program that can automatically make multiple transactions. The thing is, right now I first connect to Hyperledger Fabric and then run the function through a for loop.

This is fairly fast, but I'm looking to greatly improve the speed. This is the code that initiates the connection:

init() {
        return this.businessNetworkConnection.connect(this.connectionProfile, this.businessNetworkIdentifier, participantId, participantPwd)
            .then((result) => {
                console.log(chalk.green('Connected to Hyperledger!'));
                this.businessNetworkDefinition = result;
            })
            .catch(function (error) {
                console.log('An error occured: ', chalk.bold.red(error));
            });
    }

This is the code that allows me to make transactions on the ledger:

makeTransaction(fromID, toID, funds) {
        const METHOD = 'makeTransaction';
        let from;
        let walletRegistry;
        let to;

        return this.businessNetworkConnection.getAssetRegistry('org.acme.Wallet')
            .then((registry) => {
                console.log(1);
                walletRegistry = registry;
                return walletRegistry.get(fromID);
            })
            .then((fromm) => {
                console.log(2);
                from = fromm;
                return walletRegistry.get(toID);
            })
            .then((too) => {
                to = too;
            })
            .then(() => {
                let serializer = this.businessNetworkDefinition.getSerializer();
                let resource = serializer.fromJSON({
                    "$class": "org.acme.Transfer",
                    "amount": funds,
                    "from": {
                        "$class": "org.acme.Wallet",
                        "id": from.getIdentifier(),
                        "balance": from.balance,
                        "owner": "resource:org.acme.Client#" + from.owner.getIdentifier()
                    },
                    "to": {
                        "$class": "org.acme.Wallet",
                        "id": to.getIdentifier(),
                        "balance": to.balance,
                        "owner": "resource:org.acme.Client#" + to.owner.getIdentifier()
                    }
                });

                return this.businessNetworkConnection.submitTransaction(resource);
            })
            .catch(function (error) {
                throw (error);
            })
    }

But the function that right now makes the transaction happen looks like this.

static transfer(fromID, toID, funds) {
        let bm = new BlockchainManager();
        return bm.init()
            .then(() => {
                return bm.makeTransaction(fromID, toID, funds);
            })
            .then(() => {
                console.log('Success!');
            })
            .catch(function (error) {
                console.log('An error occured: ', chalk.bold.red(error));
                process.exit(1);
            });
    }

I don't think this is the best way to make a lot of transactions (I'm looking to run over 1000 per second at some point). Which would be the best way to program this?

Luna Debb
  • 49
  • 7
  • Regarding `walletRegistry`, `from` and `to`, have a look at [How do I access previous promise results in a `.then()` chain?](https://stackoverflow.com/q/28250680/1048572) – Bergi Oct 30 '17 at 01:02
  • Where's the loop? What is "fairly fast" (what have you measured)? What do you think can be improved? Have you done any profiling, do you know what the bottleneck is? – Bergi Oct 30 '17 at 01:05
  • Are BlockChainManagers reusable? If so then consider drawing on a pool of them rather than creating new and initializing for every transfer. I'm sure there must be some suitable off-the-shelf paradigm for managing the pool ... – Roamer-1888 Oct 30 '17 at 04:34
  • ... but do your profiling before committing to that or anything else. – Roamer-1888 Oct 30 '17 at 04:37
  • `serializer` is another candidate for reuse. – Roamer-1888 Oct 30 '17 at 04:58

2 Answers2

0

Have you tried using Promise.all? I think is works like:

Promise.all([asyncFunc1(), asyncFunc2(), asyncFunc3(),... ])
.then(function(result){...})
.catch(function(error){...});

The .then() is called when all the promises have been resolved.

yen
  • 1,769
  • 2
  • 15
  • 43
  • What I'd normally do is to do a `for(let i = 0; i < am ; I++){ transfer(i,i+1,i*29); } ` so how would you program it? – Luna Debb Oct 30 '17 at 00:14
  • I think the bluebird implementation of promises is supposedly(?) more performant if you care about speed... regardless, their example using `writefileAsync` seems to point in the right direction: http://bluebirdjs.com/docs/api/promise.all.html They also have a promise.join: http://bluebirdjs.com/docs/api/promise.join.html Beyond that, I am not an expert in how to deploy these for your case. Maybe a for loop really _is_ faster, who knows... – yen Oct 30 '17 at 00:27
0

you can do.

let all_promise = [];
/*
* your loop here
* for(let i = 0; i < am ; I++){
*    all_promise.push(transfer(i,i+1,i*29);
*  } 
*/
Promise.all(all_promise).then(arr => {
      // arr is the map arr of all the promises that "transfer()" method returned
      // you can Iterate the arr since its the resolve value of all the promises that was push from all_promise . you need to refactor big time in your code.
})

I just comment out the for loop for you to have an idea.. the idea of this is you push all the promises that not yet resolve into an array then pass that array to the Promise.all the then part will be the array of the resolve values