Skip to content

Commit 982edda

Browse files
authored
GetHistoryForKey to return correct data (#375)
* GetHistoryForKey to return correct data The 2.5 release used an updated protobuf js library; this has meant changes across the codebase to use this new library, subtly different API.. this function was sadly missed. Signed-off-by: Matthew B White <whitemat@uk.ibm.com> * Fix unit tests Signed-off-by: Matthew B White <whitemat@uk.ibm.com> Signed-off-by: Matthew B White <whitemat@uk.ibm.com>
1 parent 21c4377 commit 982edda

File tree

4 files changed

+110
-180
lines changed

4 files changed

+110
-180
lines changed

libraries/fabric-shim/lib/iterators.js

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
const logger = require('./logger').getLogger('lib/iterators.js');
1010

11-
const {ledger} = require('@hyperledger/fabric-protos');
11+
const { ledger } = require('@hyperledger/fabric-protos');
1212

1313
/**
1414
* CommonIterator allows a chaincode to check whether any more result(s)
@@ -20,16 +20,16 @@ const {ledger} = require('@hyperledger/fabric-protos');
2020
class CommonIterator {
2121

2222
/**
23-
* constructor
23+
* constructor
2424
*
2525
* Note that the decoded payload will be a protobuf of type
2626
* fabprotos.protos.QueryResponse
2727
*
28-
* @param {ChaincodeSupportClient} handler client handler
29-
* @param {string} channel_id channel id
30-
* @param {string} txID transaction id
31-
* @param {object} response decoded payload
32-
*/
28+
* @param {ChaincodeSupportClient} handler client handler
29+
* @param {string} channel_id channel id
30+
* @param {string} txID transaction id
31+
* @param {object} response decoded payload
32+
*/
3333
constructor(handler, channel_id, txID, response, type) {
3434
this.type = type;
3535
this.handler = handler;
@@ -42,58 +42,57 @@ class CommonIterator {
4242
}
4343

4444
/**
45-
* close the iterator.
46-
* @async
47-
* @return {promise} A promise that is resolved with the close payload or rejected
48-
* if there is a problem
49-
*/
45+
* close the iterator.
46+
* @async
47+
* @return {promise} A promise that is resolved with the close payload or rejected
48+
* if there is a problem
49+
*/
5050
async close() {
5151
logger.debug('close called on %s iterator for txid: %s', this.type, this.txID);
5252
return await this.handler.handleQueryStateClose(this.response.getId(), this.channel_id, this.txID);
5353
}
5454

5555
/*
56-
* decode the payload depending on the type of iterator.
57-
* @param {object} bytes
58-
*/
59-
_getResultFromBytes(bytes) {
60-
if (this.type === 'QUERY') {
61-
return ledger.queryresult.KV.deserializeBinary(bytes.getResultbytes());
62-
} else if (this.type === 'HISTORY') {
63-
return ledger.queryresult.KeyModification.deserializeBinary(bytes.getResultbytes());
64-
}
65-
throw new Error('Iterator constructed with unknown type: ' + this.type);
66-
}
67-
68-
69-
/*
70-
* creates a return value
71-
*/
56+
* creates a return value
57+
*/
7258
_createAndEmitResult() {
73-
const queryResult = {};
7459
const resultsList = this.response.getResultsList();
60+
let queryResult;
7561

76-
const queryResultPb = this._getResultFromBytes(resultsList[this.currentLoc]);
77-
queryResult.value = {value:Buffer.from(queryResultPb.getValue())};
78-
/* istanbul ignore else*/
79-
if ('getKey' in queryResultPb) {
80-
queryResult.value.key = Buffer.from(queryResultPb.getKey()).toString();
62+
// established external API has a very specific structure here
63+
// so need to 'fluff' up this structure to match
64+
// Not all queryResults have the same methods
65+
if (this.type === 'QUERY') {
66+
const queryResultPb = ledger.queryresult.KV.deserializeBinary((resultsList[this.currentLoc]).getResultbytes());
67+
queryResult = {
68+
key: queryResultPb.getKey(),
69+
value: Buffer.from(queryResultPb.getValue())
70+
};
71+
} else if (this.type === 'HISTORY') {
72+
const queryResultPb = ledger.queryresult.KeyModification.deserializeBinary((resultsList[this.currentLoc]).getResultbytes());
73+
queryResult = {
74+
txId: queryResultPb.getTxId(),
75+
value: Buffer.from(queryResultPb.getValue()),
76+
isDelete: queryResultPb.getIsDelete(),
77+
timestamp: queryResultPb.getTimestamp().toObject()
78+
79+
};
80+
} else {
81+
throw new Error('Iterator constructed with unknown type: ' + this.type);
8182
}
8283

83-
8484
this.currentLoc++;
8585

86-
queryResult.done = false;
87-
return queryResult;
86+
return {value: queryResult, done: false};
8887
}
8988

9089
/**
91-
* Get the next value and return it through a promise.
92-
* @async
93-
* @return {promise} a promise that is fulfilled with an object { value: (next value) },
94-
* is fulfilled with an object { done: true } if there is no more value,
95-
* or is rejected if any error occurs.
96-
*/
90+
* Get the next value and return it through a promise.
91+
* @async
92+
* @return {promise} a promise that is fulfilled with an object { value: (next value) },
93+
* is fulfilled with an object { done: true } if there is no more value,
94+
* or is rejected if any error occurs.
95+
*/
9796
async next() {
9897
// check to see if there are some results left in the current result set
9998
const resultsList = this.response.getResultsList();
@@ -112,7 +111,7 @@ class CommonIterator {
112111
throw err;
113112
}
114113
}
115-
return {done: true};
114+
return { done: true };
116115
}
117116

118117
}

0 commit comments

Comments
 (0)