in ngo-lambda/src/invoke.js [24:181]
async function invokeChaincode(request) {
logger.info("=== Invoke Function Start ===");
let error_message_displayable = null;
let error_message = null;
let transactionId = null;
let retriable = false;
try {
// first setup the client for this org
let channel = await setupChannel();
let fabricClient = await setupFabricClient();
transactionId = fabricClient.newTransactionID();
logger.info("=== Created transactionId ===" + transactionId.getTransactionID());
request['txId'] = transactionId;
request['targets'] = channel.getPeers();
// send proposal to endorsing peers
logger.info('##### invokeChaincode - Invoke transaction request to Fabric');
let results = await channel.sendTransactionProposal(request).catch(err => {
throw err;
});
// the returned object has both the endorsement results
// and the actual proposal, the proposal will be needed
// later when we send a transaction to the ordering service
let proposalResponses = results[0];
let proposal = results[1];
// let's have a look at the responses to see if they are
// all good, if good they will also include signatures
// required to be committed
let successfulResponses = true;
for (let i in proposalResponses) {
let oneSuccessfulResponse = false;
if (proposalResponses && proposalResponses[i].response &&
proposalResponses[i].response.status === 200) {
oneSuccessfulResponse = true;
logger.info('##### invokeChaincode - received successful proposal response');
} else {
logger.error('##### invokeChaincode - received unsuccessful proposal response');
}
successfulResponses = successfulResponses & oneSuccessfulResponse;
}
if (successfulResponses) {
logger.info(util.format(
'##### invokeChaincode - Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s"',
proposalResponses[0].response.status, proposalResponses[0].response.message));
// wait for the channel-based event hub to tell us
// that the commit was good or bad on each peer in our organization
let promises = [];
let event_hubs = channel.getChannelEventHubsForOrg();
event_hubs.forEach((eh) => {
logger.info('##### invokeChaincode - invokeEventPromise - setting up event handler');
let invokeEventPromise = new Promise((resolve, reject) => {
let event_timeout = setTimeout(() => {
let message = 'REQUEST_TIMEOUT:' + eh.getPeerAddr();
logger.error(message);
eh.disconnect();
}, 10000);
eh.registerTxEvent(transactionId.getTransactionID(), (tx, code, block_num) => {
logger.info('##### invokeChaincode - The invoke chaincode transaction has been committed on peer %s',eh.getPeerAddr());
logger.info('##### invokeChaincode - Transaction %s has status of %s in block %s', tx, code, block_num);
clearTimeout(event_timeout);
if (code !== 'VALID') {
let message = util.format('##### invokeChaincode - The invoke chaincode transaction was invalid, code:%s',code);
logger.error(message);
return reject(new Error(message));
} else {
let message = '##### invokeChaincode - The invoke chaincode transaction was valid.';
logger.info(message);
return resolve(message);
}
}, (err) => {
clearTimeout(event_timeout);
logger.error(err);
reject(err);
},
// the default for 'unregister' is true for transaction listeners
// so no real need to set here, however for 'disconnect'
// the default is false as most event hubs are long running
// in this use case we are using it only once
{unregister: true, disconnect: true}
);
eh.connect();
});
promises.push(invokeEventPromise);
});
let orderer_request = {
txId: transactionId,
proposalResponses: proposalResponses,
proposal: proposal
};
let sendPromise = channel.sendTransaction(orderer_request);
// put the send to the ordering service last so that the events get registered and
// are ready for the orderering and committing
promises.push(sendPromise);
let results = await Promise.all(promises);
logger.info(util.format('##### invokeChaincode ------->>> R E S P O N S E : %j', results));
let response = results.pop(); // ordering service results are last in the results
if (response.status === 'SUCCESS') {
logger.info('##### invokeChaincode - Successfully sent transaction to the ordering service.');
} else {
error_message = util.format('##### invokeChaincode - Failed to order the transaction. Error code: %s',response.status);
error_message_displayable = response.status;
logger.info(error_message);
}
// now see what each of the event hubs reported
for (let i in results) {
let event_hub_result = results[i];
let event_hub = event_hubs[i];
logger.info('##### invokeChaincode - Event results for event hub :%s',event_hub.getPeerAddr());
if (typeof event_hub_result === 'string') {
logger.info('##### invokeChaincode - ' + event_hub_result);
}
else {
if (!error_message) error_message = event_hub_result.toString();
logger.info('##### invokeChaincode - ' + event_hub_result.toString());
}
}
}
else {
error_message = util.format('##### invokeChaincode - Failed to send Proposal and receive all good ProposalResponse. Status code: ' +
proposalResponses[0].status + ', ' +
proposalResponses[0].message + '\n' +
proposalResponses[0].stack);
logger.info(error_message);
error_message_displayable = proposalResponses[0].message;
}
} catch (error) {
logger.error('##### invokeChaincode - Failed to invoke due to error: ' + error.stack ? error.stack : error);
error_message = error.toString();
error_message_displayable = error.toString();
retriable = true;
}
if (!error_message) {
let message = util.format(
'##### invokeChaincode - Successfully invoked chaincode %s, function %s, on the channel \'%s\' for transaction ID: %s',
request.chaincodeId, request.fcn, request.chainId, transactionId.getTransactionID());
logger.info(message);
let response = {};
response.transactionId = transactionId.getTransactionID();
return response;
}
else {
let message = util.format('##### invokeChaincode - Failed to invoke chaincode :%s', error_message);
logger.error(message);
let displayMessage = retriable ? error_message_displayable + " Please retry your request." : error_message_displayable;
throw new Error(displayMessage);
}
};