Skip to content

Commit

Permalink
Merge "[FAB-6679] NodeSDK - CCP timeouts"
Browse files Browse the repository at this point in the history
  • Loading branch information
jimthematrix authored and Gerrit Code Review committed Oct 26, 2017
2 parents ebe383e + 2161c2b commit 3f5b90a
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 42 deletions.
4 changes: 2 additions & 2 deletions fabric-client/lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,8 +879,8 @@ var Client = class extends BaseClient {

/**
* @typedef {Object} ChaincodeInstallRequest
* @property {Peer[]} targets - Optional. An array of Peer objects that the
* chaincode will be installed on. When excluded, the peers assigned
* @property {Peer[]} targets - Optional. An array of Peer objects where the
* chaincode will be installed. When excluded, the peers assigned
* to this client's organization will be used as defined in the
* network configuration. If the 'channels' property is included,
* the target peers will be based the peers defined in the channels.
Expand Down
73 changes: 56 additions & 17 deletions fabric-client/lib/impl/NetworkConfig_1_0.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,29 @@ var CertificateAuthority = require('../CertificateAuthority.js');
var FabricCA = require('fabric-ca-client');

var logger = utils.getLogger('NetworkConfig101.js');
var CHANNELS_CONFIG = 'channels';
var ORGS_CONFIG = 'organizations';
var PEERS_CONFIG = 'peers';
var ORDERERS_CONFIG = 'orderers';
var CAS_CONFIG = 'certificateAuthorities';
var TLS_CACERTS = 'tlsCACerts';
var ADMIN_PRIVATE_KEY = 'adminPrivateKey';
var ADMIN_CERT = 'signedCert';
var GRPC_CONNECTION_OPTIONS = 'grpcOptions';
var HTTP_CONNECTION_OPTIONS = 'httpOptions';
var URL = 'url';
var EVENT_URL = 'eventUrl';
var NAME = 'name';
var CANAME = 'caName';
var PEM = 'pem';
var PATH = 'path';
var REGISTRAR = 'registrar';
const CHANNELS_CONFIG = 'channels';
const ORGS_CONFIG = 'organizations';
const PEERS_CONFIG = 'peers';
const ORDERERS_CONFIG = 'orderers';
const CAS_CONFIG = 'certificateAuthorities';
const TLS_CACERTS = 'tlsCACerts';
const ADMIN_PRIVATE_KEY = 'adminPrivateKey';
const ADMIN_CERT = 'signedCert';
const GRPC_CONNECTION_OPTIONS = 'grpcOptions';
const HTTP_CONNECTION_OPTIONS = 'httpOptions';
const URL = 'url';
const EVENT_URL = 'eventUrl';
const NAME = 'name';
const CANAME = 'caName';
const PEM = 'pem';
const PATH = 'path';
const REGISTRAR = 'registrar';
const ENDORSER = 1;
const ORDERER = 2;
const EVENTHUB = 3;
const EVENTREG = 4;
const TYPES = ['unknown', 'endorser', 'orderer', 'eventHub', 'eventReg'];
const REQUEST_TIMEOUT = 'request-timeout';
var ROLES = Constants.NetworkConfig.ROLES;

/**
Expand Down Expand Up @@ -170,6 +176,7 @@ var NetworkConfig_1_0 = class {
let opts = {};
opts.pem = getTLSCACert(peer_config);
Object.assign(opts, peer_config[GRPC_CONNECTION_OPTIONS]);
this.addTimeout(opts, ENDORSER);
peer = new Peer(peer_config[URL], opts);
peer.setName(name);
if(channel_org) {
Expand All @@ -185,6 +192,36 @@ var NetworkConfig_1_0 = class {
return peer;
}

addTimeout(opts, type) {
var method = 'addTimeout';
if(opts && opts[REQUEST_TIMEOUT]) {
logger.debug('%s - request-timeout exist',method);
return;
}
if(opts && this.hasClient() &&
this._network_config.client.connection &&
this._network_config.client.connection.timeout) {
let timeouts = this._network_config.client.connection.timeout;
let timeout = '';
if(type === ENDORSER && timeouts.peer && timeouts.peer.endorser) {
timeout = timeouts.peer.endorser;
} else if(type === ORDERER && timeouts.orderer) {
timeout = timeouts.orderer;
} else if(type === EVENTHUB && timeouts.peer && timeouts.peer.eventHub) {
timeout = timeouts.peer.eventHub;
} else if(type === EVENTREG && timeouts.peer && timeouts.peer.eventReg) {
timeout = timeouts.peer.eventReg;
}

if(!isNaN(timeout)) {
timeout = timeout * 1000;
opts[REQUEST_TIMEOUT] = timeout;
} else {
logger.warn('%s - timeout value is not a number for the %s : %s',method, TYPES[type], timeout);
}
}
}

getEventHub(name) {
var method = 'getEventHub';
logger.debug('%s - name %s',method, name);
Expand All @@ -195,6 +232,7 @@ var NetworkConfig_1_0 = class {
let opts = {};
opts.pem = getTLSCACert(peer_config);
Object.assign(opts, peer_config[GRPC_CONNECTION_OPTIONS]);
this.addTimeout(opts, EVENTREG);
event_hub = new EventHub(this._client_context);
event_hub.setPeerAddr(peer_config[EVENT_URL], opts);
}
Expand All @@ -213,6 +251,7 @@ var NetworkConfig_1_0 = class {
let opts = {};
opts.pem = getTLSCACert(orderer_config);
Object.assign(opts, orderer_config[GRPC_CONNECTION_OPTIONS]);
this.addTimeout(opts, ORDERER);
orderer = new Orderer(orderer_config[URL], opts);
orderer.setName(orderer_config[NAME]);
}
Expand Down
36 changes: 28 additions & 8 deletions test/fixtures/org1.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "global-trade-network"

#
# Describes the type of the backend, "hl-fabric" for Hyperledger Fabric, "hl-stl" for Hyperledger
# Describes the type of the backend, "hl-fabric" for Hyperledger Fabric, "hl-stl" for Hyperledger
# Sawtooth Lake, etc.
#
type: "hl-fabric@^1.0.0"
Expand All @@ -22,19 +22,39 @@ client:
# defined under "organizations"
organization: Org1

# Since the node.js SDK supports pluggable KV stores, the properties under "credentialStore"
# set connection timeouts for the peer and orderer for the client
connection:
timeout:
peer:
# the timeout in seconds to be used on requests to a peer,
# for example 'sendTransactionProposal'
endorser: 120
# the timeout in seconds to be used by applications when waiting for an
# event to occur. This time should be used in a javascript timer object
# that will cancel the event registration with the event hub instance.
eventHub: 60
# the timeout in seconds to be used when setting up the connection
# with the peer's event hub. If the peer does not acknowledge the
# connection within the time, the application will be notified over the
# error callback if provided.
eventReg: 3
# the timeout in seconds to be used on request to the orderer,
# for example
orderer: 30

# Since the node.js SDK supports pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
# Specific to FileKeyValueStore.js. Can be others if using an alternative impl. For instance,
# Specific to FileKeyValueStore.js. Can be others if using an alternative impl. For instance,
# CouchDBKeyValueStore.js would require an object here for properties like url, db name, etc.
path: "/tmp/hfc-kvs/org1"

# Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js requires a key store. PKCS#11 based implementations does
# Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js requires a key store. PKCS#11 based implementations does
# not.
cryptoStore:
# Specific to the underlying KeyValueStore that backs the crypto key store.
# Specific to the underlying KeyValueStore that backs the crypto key store.
path: "/tmp/hfc-cvs/org1"

# Specific to Composer environment
wallet: wallet-name
wallet: wallet-name
36 changes: 28 additions & 8 deletions test/fixtures/org2.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "global-trade-network"

#
# Describes the type of the backend, "hl-fabric" for Hyperledger Fabric, "hl-stl" for Hyperledger
# Describes the type of the backend, "hl-fabric" for Hyperledger Fabric, "hl-stl" for Hyperledger
# Sawtooth Lake, etc.
#
type: "hl-fabric@^1.0.0"
Expand All @@ -22,19 +22,39 @@ client:
# defined under "organizations"
organization: Org2

# Since the node.js SDK supports pluggable KV stores, the properties under "credentialStore"
# set connection timeouts for the peer and orderer for the client
connection:
timeout:
peer:
# the timeout in seconds to be used on requests to a peer,
# for example 'sendTransactionProposal'
endorser: 120
# the timeout in seconds to be used by applications when waiting for an
# event to occur. This time should be used in a javascript timer object
# that will cancel the event registration with the event hub instance.
eventHub: 60
# the timeout in seconds to be used when setting up the connection
# with the peer's event hub. If the peer does not acknowledge the
# connection within the time, the application will be notified over the
# error callback if provided.
eventReg: 3
# the timeout in seconds to be used on request to the orderer,
# for example
orderer: 30

# Since the node.js SDK supports pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
# Specific to FileKeyValueStore.js. Can be others if using an alternative impl. For instance,
# Specific to FileKeyValueStore.js. Can be others if using an alternative impl. For instance,
# CouchDBKeyValueStore.js would require an object here for properties like url, db name, etc.
path: "/tmp/hfc-kvs/org2"

# Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js requires a key store. PKCS#11 based implementations does
# Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js requires a key store. PKCS#11 based implementations does
# not.
cryptoStore:
# Specific to the underlying KeyValueStore that backs the crypto key store.
# Specific to the underlying KeyValueStore that backs the crypto key store.
path: "/tmp/hfc-cvs/org2"

# Specific to Composer environment
wallet: wallet-name
wallet: wallet-name
2 changes: 1 addition & 1 deletion test/integration/e2e/e2eUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ function instantiateChaincode(userOrg, chaincode_path, version, language, upgrad
resolve();
}
}, (err) => {
t.fail('The was a problem with the instantiate event '+err);
t.fail('There was a problem with the instantiate event '+err);
clearTimeout(handle);
eh.unregisterTxEvent(deployId);
});
Expand Down
3 changes: 1 addition & 2 deletions test/integration/e2e/join-channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ function joinChannel(org, t) {
block : genesis_block,
txId : tx_id
};
let sendPromise = channel.joinChannel(request);
let sendPromise = channel.joinChannel(request, 30000);
return Promise.all([sendPromise].concat(eventPromises));
}, (err) => {
t.fail('Failed to enroll user \'admin\' due to error: ' + err.stack ? err.stack : err);
Expand All @@ -215,4 +215,3 @@ function joinChannel(org, t) {
t.fail('Failed to join channel due to error: ' + err.stack ? err.stack : err);
});
}

4 changes: 2 additions & 2 deletions test/integration/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ async function createChannel(t) {
txId : tx_id
};

results = await channel.joinChannel(request); //admin from org2
results = await channel.joinChannel(request, 30000); //admin from org2
logger.debug(util.format('Join Channel R E S P O N S E using default targets: %j', results));

// first of the results should not have good status as submitter does not have permission
Expand Down Expand Up @@ -252,7 +252,7 @@ async function createChannel(t) {
txId : tx_id
};

results = await channel.joinChannel(request); //logged in as org1
results = await channel.joinChannel(request, 30000); //logged in as org1
logger.debug(util.format('Join Channel R E S P O N S E for a string target: %j', results));

if(results && results[0] && results[0].response && results[0].response.status == 200) {
Expand Down
9 changes: 8 additions & 1 deletion test/integration/network-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ test('\n\n***** use the network configuration file *****\n\n', function(t) {
//targets - Letting default to all endorsing peers defined on the channel in the network configuration
};

return channel.sendTransactionProposal(request, 3000); //logged in as org1 user
return channel.sendTransactionProposal(request); //logged in as org1 user
}).then((results) => {
var proposalResponses = results[0];
var proposal = results[1];
Expand All @@ -439,6 +439,13 @@ test('\n\n***** use the network configuration file *****\n\n', function(t) {
one_good = true;
} else {
t.fail('transaction proposal was bad');
if( proposal_response.response && proposal_response.response.status) {
t.comment(' response status:' + proposal_response.response.status +
' message:' + proposal_response.response.message);
} else {
t.fail('transaction response was unknown' );
logger.error('transaction response was unknown %s', proposal_response)
}
}
all_good = all_good & one_good;
}
Expand Down
30 changes: 29 additions & 1 deletion test/unit/network-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,38 @@ test('\n\n ** configuration testing **\n\n', function (t) {
t.equals(1, peers.length, ' Check to see that we got 1 peer');
t.equals('grpcs://localhost:7051', peers[0].getUrl(), ' Check to see if we got the right peer for org1 that is endorsing and on the channel');

let opts = {somesetting : 4};
client._network_config.addTimeout(opts,1);
t.equals(opts['somesetting'], 4, 'check that existing settings are still there');
t.equals(opts['request-timeout'], 120000, 'check that endorser timeout was added');
opts = {};
client._network_config.addTimeout(opts,2);
t.equals(opts['request-timeout'], 30000, 'check that orderer timeout was added');
opts = {};
client._network_config.addTimeout(opts,3);
t.equals(opts['request-timeout'], 60000, 'check that eventHub timeout was added');
opts = {};
client._network_config.addTimeout(opts,4);
t.equals(opts['request-timeout'], 3000, 'check that eventReg timeout was added');
opts = {};
opts['request-timeout'] = 5000;
client._network_config.addTimeout(opts,4);
t.equals(opts['request-timeout'], 5000, 'check that timeout did not change');
client._network_config._network_config.client.connection.timeout.peer.eventHub = '2s';
opts = {};
client._network_config.addTimeout(opts,3);
t.equals(opts['request-timeout'], undefined, 'check that timeout did not change');

let peer = client._network_config.getPeer('peer0.org1.example.com');
t.equals(peer._options['request-timeout'],120000, ' check that we get this peer endorser timeout set');
let orderer = client._network_config.getOrderer('orderer.example.com');
t.equals(orderer._options['request-timeout'],30000, ' check that we get this orderer timeout set');
let eventHub = client._network_config.getEventHub('peer0.org1.example.com');
t.equals(eventHub._ep._options['request-timeout'],3000, ' check that we get this eventHub timeout set');

},
null,
'2 Should be able to instantiate a new instance of "Channel" with the definition in the network configuration'
'2 Should be able to run a number of test without error'
);

t.doesNotThrow(
Expand Down

0 comments on commit 3f5b90a

Please sign in to comment.