Skip to content

Commit 525d7c6

Browse files
committed
refactor: move batching fallback logic to handler
Signed-off-by: Sourav <souravkjha2007@gmail.com>
1 parent c560719 commit 525d7c6

4 files changed

Lines changed: 61 additions & 29 deletions

File tree

libraries/fabric-shim/lib/handler.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,14 @@ class ChaincodeMessageHandler {
374374
handleMessage(msg, this, 'invoke');
375375
}
376376

377+
async handleGetMultipleStates(keys, channel_id, txid) {
378+
return await Promise.all(keys.map(key => this.handleGetState('', key, channel_id, txid)));
379+
}
380+
381+
async handleGetMultiplePrivateData(collection, keys, channel_id, txid) {
382+
return await Promise.all(keys.map(key => this.handleGetState(collection, key, channel_id, txid)));
383+
}
384+
377385
async handleGetState(collection, key, channel_id, txId) {
378386
const msgPb = new peer.GetState();
379387
msgPb.setKey(key);

libraries/fabric-shim/lib/stub.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -946,12 +946,11 @@ class ChaincodeStub {
946946
*/
947947
async getMultipleStates(keys) {
948948
logger.debug('getMultipleStates called with keys:%j', keys);
949-
if (!Array.isArray(keys)) {
949+
if (!Array.isArray(keys) || keys.some((key) => typeof key !== 'string')) {
950950
throw new Error('keys must be an array of strings');
951951
}
952952

953-
const promises = keys.map(key => this.getState(key));
954-
return await Promise.all(promises);
953+
return await this.handler.handleGetMultipleStates(keys, this.channel_id, this.txId);
955954
}
956955

957956
/**
@@ -964,15 +963,14 @@ class ChaincodeStub {
964963
*/
965964
async getMultiplePrivateData(collection, keys) {
966965
logger.debug('getMultiplePrivateData called with collection:%s, keys:%j', collection, keys);
967-
if (!collection || typeof collection !== 'string') {
966+
if (typeof collection !== 'string') {
968967
throw new Error('collection must be a valid string');
969968
}
970-
if (!Array.isArray(keys)) {
969+
if (!Array.isArray(keys) || keys.some((key) => typeof key !== 'string')) {
971970
throw new Error('keys must be an array of strings');
972971
}
973972

974-
const promises = keys.map(key => this.getPrivateData(collection, key));
975-
return await Promise.all(promises);
973+
return await this.handler.handleGetMultiplePrivateData(collection, keys, this.channel_id, this.txId);
976974
}
977975

978976
/**

libraries/fabric-shim/test/unit/handler.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,46 @@ describe('Handler', () => {
899899
});
900900
});
901901

902+
describe('handleGetMultipleStates', () => {
903+
let handleGetStateStub;
904+
afterEach(() => {
905+
sandbox.restore();
906+
});
907+
908+
it('should stub handleGetState and return buffered values', async () => {
909+
const mockStream = {write: sinon.stub(), end: sinon.stub()};
910+
const handler = new Handler.ChaincodeMessageHandler(mockStream, mockChaincodeImpl);
911+
handleGetStateStub = sandbox.stub(handler, 'handleGetState').resolves(Buffer.from('value'));
912+
913+
const result = await handler.handleGetMultipleStates(['key1', 'key2'], 'theChannelID', 'theTxID');
914+
915+
expect(result).to.deep.equal([Buffer.from('value'), Buffer.from('value')]);
916+
expect(handleGetStateStub.calledTwice).to.be.true;
917+
expect(handleGetStateStub.firstCall.args).to.deep.equal(['', 'key1', 'theChannelID', 'theTxID']);
918+
expect(handleGetStateStub.secondCall.args).to.deep.equal(['', 'key2', 'theChannelID', 'theTxID']);
919+
});
920+
});
921+
922+
describe('handleGetMultiplePrivateData', () => {
923+
let handleGetStateStub;
924+
afterEach(() => {
925+
sandbox.restore();
926+
});
927+
928+
it('should stub handleGetState and return buffered values', async () => {
929+
const mockStream = {write: sinon.stub(), end: sinon.stub()};
930+
const handler = new Handler.ChaincodeMessageHandler(mockStream, mockChaincodeImpl);
931+
handleGetStateStub = sandbox.stub(handler, 'handleGetState').resolves(Buffer.from('value'));
932+
933+
const result = await handler.handleGetMultiplePrivateData('collection1', ['key1', 'key2'], 'theChannelID', 'theTxID');
934+
935+
expect(result).to.deep.equal([Buffer.from('value'), Buffer.from('value')]);
936+
expect(handleGetStateStub.calledTwice).to.be.true;
937+
expect(handleGetStateStub.firstCall.args).to.deep.equal(['collection1', 'key1', 'theChannelID', 'theTxID']);
938+
expect(handleGetStateStub.secondCall.args).to.deep.equal(['collection1', 'key2', 'theChannelID', 'theTxID']);
939+
});
940+
});
941+
902942
describe('handleGetState', () => {
903943
const key = 'theKey';
904944
const collection = '';

libraries/fabric-shim/test/unit/stub.js

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,26 +1108,19 @@ describe('Stub', () => {
11081108

11091109
beforeEach(() => {
11101110
stub = new Stub({
1111-
handleGetState: sinon.stub().resolves(Buffer.from('value'))
1111+
handleGetMultipleStates: sinon.stub().resolves([Buffer.from('value1'), Buffer.from('value2')])
11121112
}, 'dummyChannelId', 'dummyTxid', chaincodeInput);
11131113
});
11141114

11151115
it('should throw an error if keys is not an array', async () => {
11161116
await expect(stub.getMultipleStates('not-an-array')).to.be.rejectedWith(/keys must be an array of strings/);
11171117
});
11181118

1119-
it('should call getState for each key and return the results', async () => {
1120-
sandbox.stub(stub, 'getState').callsFake(async (key) => {
1121-
if (key === 'key1') {
1122-
return Buffer.from('value1');
1123-
} else if (key === 'key2') {
1124-
return Buffer.from('value2');
1125-
}
1126-
});
1127-
1119+
it('should call call handleGetMultipleStates on the handler and return the results', async () => {
11281120
const results = await stub.getMultipleStates(['key1', 'key2']);
11291121
expect(results).to.deep.equal([Buffer.from('value1'), Buffer.from('value2')]);
1130-
sinon.assert.calledTwice(stub.getState);
1122+
sinon.assert.calledOnce(stub.handler.handleGetMultipleStates);
1123+
sinon.assert.calledWith(stub.handler.handleGetMultipleStates, ['key1', 'key2'], 'dummyChannelId', 'dummyTxid');
11311124
});
11321125
});
11331126

@@ -1136,7 +1129,7 @@ describe('Stub', () => {
11361129

11371130
beforeEach(() => {
11381131
stub = new Stub({
1139-
handleGetState: sinon.stub().resolves(Buffer.from('value'))
1132+
handleGetMultiplePrivateData: sinon.stub().resolves([Buffer.from('value1'), Buffer.from('value2')])
11401133
}, 'dummyChannelId', 'dummyTxid', chaincodeInput);
11411134
});
11421135

@@ -1148,18 +1141,11 @@ describe('Stub', () => {
11481141
await expect(stub.getMultiplePrivateData('collection', 'not-an-array')).to.be.rejectedWith(/keys must be an array of strings/);
11491142
});
11501143

1151-
it('should call getPrivateData for each key and return the results', async () => {
1152-
sandbox.stub(stub, 'getPrivateData').callsFake(async (collection, key) => {
1153-
if (key === 'key1') {
1154-
return Buffer.from('value1');
1155-
} else if (key === 'key2') {
1156-
return Buffer.from('value2');
1157-
}
1158-
});
1159-
1144+
it('should call handleGetMultiplePrivateData on the handler and return the results', async () => {
11601145
const results = await stub.getMultiplePrivateData('collection', ['key1', 'key2']);
11611146
expect(results).to.deep.equal([Buffer.from('value1'), Buffer.from('value2')]);
1162-
sinon.assert.calledTwice(stub.getPrivateData);
1147+
sinon.assert.calledOnce(stub.handler.handleGetMultiplePrivateData);
1148+
sinon.assert.calledWith(stub.handler.handleGetMultiplePrivateData, 'collection', ['key1', 'key2'], 'dummyChannelId', 'dummyTxid');
11631149
});
11641150
});
11651151

0 commit comments

Comments
 (0)