diff --git a/docs/tutorials/query-peers.md b/docs/tutorials/query-peers.md index 967888a2e4..ec6625d089 100644 --- a/docs/tutorials/query-peers.md +++ b/docs/tutorials/query-peers.md @@ -16,11 +16,15 @@ by default. This will evaluate all transactions on the first peer from which is can obtain a response, and only switch to another peer if this peer fails. +The default query timeout may be changed along with the query strategy. +This value will be in seconds. + ```javascript const { Gateway, DefaultQueryHandlerStrategies } = require('fabric-network'); const connectOptions = { queryHandlerOptions: { + timeout: 60, strategy: DefaultQueryHandlerStrategies.MSPID_SCOPE_SINGLE } } diff --git a/fabric-network/lib/contract.js b/fabric-network/lib/contract.js index ab7952502d..0e6ddb9fbb 100644 --- a/fabric-network/lib/contract.js +++ b/fabric-network/lib/contract.js @@ -115,6 +115,15 @@ class Contract { return this.gateway.getOptions().eventHandlerOptions; } + /** + * Get query handler options specified by the user when creating the gateway. + * @private + * @returns {Object} Query handler options. + */ + getQueryHandlerOptions() { + return this.gateway.getOptions().queryHandlerOptions; + } + /** * Create an object representing a specific invocation of a transaction * function implemented by this contract, and provides more control over diff --git a/fabric-network/lib/gateway.js b/fabric-network/lib/gateway.js index c1ab46a10c..d9839528b1 100644 --- a/fabric-network/lib/gateway.js +++ b/fabric-network/lib/gateway.js @@ -85,7 +85,9 @@ const logger = require('./logger').getLogger('Gateway'); /** * @typedef {Object} Gateway~DefaultQueryHandlerOptions - * @memberof module:fabric-network + * @memberof module:fabric- + * @property {number} [timeout = 30] The timeout period in seconds to wait for the query operation to + * complete. * @property {module:fabric-network.Gateway~QueryHandlerFactory} [strategy=MSPID_SCOPE_SINGLE] Query handling strategy * used to evaluate queries. The default is [MSPID_SCOPE_SINGLE]{@link module:fabric-network.DefaultQueryHandlerStrategies}. */ @@ -147,6 +149,7 @@ class Gateway { // default options this.options = { queryHandlerOptions: { + timeout: 30, // 30 seconds strategy: QueryStrategies.MSPID_SCOPE_SINGLE }, eventHandlerOptions: { diff --git a/fabric-network/lib/transaction.js b/fabric-network/lib/transaction.js index bc4705e331..b364c6da6d 100644 --- a/fabric-network/lib/transaction.js +++ b/fabric-network/lib/transaction.js @@ -312,11 +312,9 @@ class Transaction { const channel = this._contract.getNetwork().getChannel(); const request = this._buildRequest(args); - const commitTimeout = this._contract.getEventHandlerOptions().commitTimeout * 1000; // in ms - const timeout = this._contract.gateway.getClient().getConfigSetting('request-timeout', commitTimeout); - if (timeout < commitTimeout) { - request.request_timeout = commitTimeout; - } + // queryHandlerOption.timeout default 30 seconds + let timeout = this._contract.getQueryHandlerOptions().timeout ? this._contract.getQueryHandlerOptions().timeout : 30; + request.request_timeout = timeout * 1000; // in ms const query = new Query(channel, request); diff --git a/fabric-network/test/contract.js b/fabric-network/test/contract.js index b53cfc36af..ea33a86971 100644 --- a/fabric-network/test/contract.js +++ b/fabric-network/test/contract.js @@ -152,6 +152,14 @@ describe('Contract', () => { }); }); + describe('#getQuertHandlerOptions', () => { + it('returns query handler options from the gateway', () => { + const result = contract.getQueryHandlerOptions(); + const expected = mockGateway.getOptions().queryHandlerOptions; + result.should.deep.equal(expected); + }); + }); + describe('#createTransaction', () => { it('returns a transaction with only a name', () => { const name = 'name'; diff --git a/fabric-network/test/gateway.js b/fabric-network/test/gateway.js index b90b4b572d..6ea2764b68 100644 --- a/fabric-network/test/gateway.js +++ b/fabric-network/test/gateway.js @@ -139,6 +139,10 @@ describe('Gateway', () => { commitTimeout: 300, // 5 minutes strategy: strategy }, + queryHandlerOptions: { + timeout: 70, + strategy: strategy + }, discovery: { enabled: true, asLocalhost: true @@ -157,6 +161,10 @@ describe('Gateway', () => { commitTimeout: 300, // 5 minutes strategy: strategy }, + queryHandlerOptions: { + timeout: 70, + strategy: strategy + }, discovery: { enabled: true, asLocalhost: false @@ -353,6 +361,7 @@ describe('Gateway', () => { wallet: mockWallet, identity: 'admin', queryHandlerOptions: { + timeout: 30, strategy: QueryStrategies.MSPID_SCOPE_SINGLE } }; diff --git a/fabric-network/test/network.js b/fabric-network/test/network.js index 91f05fe4a7..7131f94ec1 100644 --- a/fabric-network/test/network.js +++ b/fabric-network/test/network.js @@ -95,6 +95,7 @@ describe('Network', () => { strategy: EventStrategies.MSPID_SCOPE_ALLFORTX }, queryHandlerOptions: { + timeout: 30, strategy: (theNetwork) => { stubQueryHandler.network = theNetwork; return stubQueryHandler; diff --git a/fabric-network/test/transaction.js b/fabric-network/test/transaction.js index 154b0f549a..c3b0aaaa22 100644 --- a/fabric-network/test/transaction.js +++ b/fabric-network/test/transaction.js @@ -98,6 +98,7 @@ describe('Transaction', () => { stubContract.getChaincodeId.returns(chaincodeId); stubContract.getEventHandlerOptions.returns({commitTimeout: 418}); + stubContract.getQueryHandlerOptions.returns({timeout: 30}); const mockClient = sinon.createStubInstance(Client); const mockGateway = sinon.createStubInstance(Gateway); @@ -433,8 +434,8 @@ describe('Transaction', () => { return expect(promise).to.be.rejectedWith('Transaction has already been invoked'); }); - it('builds correct request for invocation with long timeout', async () => { - stubContract.getEventHandlerOptions.returns({commitTimeout: 999}); + it('builds correct request for invocation with non default timeout', async () => { + stubContract.getQueryHandlerOptions.returns({timeout: 999}); await transaction.evaluate(); @@ -444,13 +445,14 @@ describe('Transaction', () => { }); }); - it('builds correct request for invocation with short timeout', async () => { - stubContract.getEventHandlerOptions.returns({commitTimeout: 3}); - + it('builds correct request for invocation with default timeout', async () => { + stubContract.getQueryHandlerOptions.returns({}); await transaction.evaluate(); const query = stubQueryHandler.evaluate.lastArg; - expect(query._request.request_timeout).to.be.undefined; + expect(query._request).to.deep.include({ + request_timeout: 30000 + }); }); }); diff --git a/fabric-network/types/index.d.ts b/fabric-network/types/index.d.ts index 53c8df1a10..be138b22fc 100644 --- a/fabric-network/types/index.d.ts +++ b/fabric-network/types/index.d.ts @@ -71,6 +71,7 @@ export interface TxEventHandler { } export interface DefaultQueryHandlerOptions { + timeout?: number; strategy?: QueryHandlerFactory; }