Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FABN-1544 Update gRPC to pure js version #247

Merged
merged 1 commit into from
Jun 12, 2020

Conversation

harrisob
Copy link
Contributor

Replace the grpc package with a pure javascript implementation.
The change involves changing the grpc message building and decoding.
Include and use the generated typescript for the protobufs.

Signed-off-by: Bret Harrison beharrison@nc.rr.com

@harrisob harrisob requested a review from a team as a code owner June 11, 2020 20:53
@harrisob
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@bestbeforetoday bestbeforetoday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of comments. Many of them I think are worth tweaking. The only showstopper is the change to the types on Checkpointer methods. Since we know certain properties will exist at runtime, you might just need to assert that properties exist in the internal event handling code when they are calling to the checkpointer to make this work if the event typings allow things to be undefined, e.g.:

checkpointer.addTransactionId(txId!);

return filteredTransactions.map((tx) => newFilteredTransactionEvent(blockEvent, tx));
}

function newFilteredTransactionEvent(blockEvent: BlockEvent, filteredTransaction: FilteredTransaction): TransactionEvent {
function newFilteredTransactionEvent(blockEvent: BlockEvent, filteredTransaction: fabproto6.protos.IFilteredTransaction): TransactionEvent {
const status = TransactionStatus.getStatusForCode(filteredTransaction.tx_validation_code);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know there will be a transaction validation code at runtime, even if the generated types allow them not to be. We could make our life much easier in TransactionStatus.getStatusForCode() by telling the TypeScript compiler there will be a value:

const status = TransactionStatus.getStatusForCode(filteredTransaction.tx_validation_code!);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const status = codeToStatusMap[code];
if (!status) {
throw new Error('Unexpected transaction status code: ' + code);
export function getStatusForCode(code: fabproto6.protos.TxValidationCode | null | undefined): string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should fix the typing issue differently to keep the code simpler and more maintainable, since we have better information about what is really there at runtime. This code works fine, even if the code turns out to be null or undefined at runtime.

export function getStatusForCode(code: fabproto6.protos.TxValidationCode): string {
	const status = fabproto6.protos.TxValidationCode[code];
	if (!status) {
		throw new Error('Unexpected transaction status code: ' + code);
	}
	return status;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -242,8 +242,8 @@ export interface EventInfo {
status?: string;
endBlockReceived?: boolean;
chaincodeEvents?: ChaincodeEvent[];
block?: Block;
filteredBlock?: FilteredBlock;
block?: fabproto6.common.IBlock;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to be careful here as the deserialized objects passed back are not the same as the protobuf TypeScript deifnitions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, a little miss leading

@@ -5,12 +5,12 @@
*/

import sinon = require('sinon');
import chai = require('chai');
const expect = chai.expect;
import 'mocha';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed, it was used to allow for debug under vscode

channelHeader.tx_id = transactionId;

const payload = new protos.common.Payload();
payload.header = new protos.common.Header();
const payload: any = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be safer to stick with the protobuf definitions rather than any and just cast values we're assigning to properties to any type at assignment where the object representation doesn't match the protobuf TypeScript. At least the typing will ensure we get the correct property names that way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -11,7 +11,7 @@ const DiscoveryService = require('./DiscoveryService.js');
const Endorsement = require('./Endorsement.js');
const Commit = require('./Commit.js');
const Query = require('./Query.js');
const fabprotos = require('fabric-protos');
const fabproto6 = require('fabric-protos');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the special reason for the '6' suffix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the conversion is based on protobufjs v6

block_header.previous_hash = proto_block_header.getPreviousHash().toBuffer().toString('hex');
block_header.data_hash = proto_block_header.getDataHash().toBuffer().toString('hex');
block_header.number = blockHeaderProto.number;
block_header.previous_hash = blockHeaderProto.previous_hash;
Copy link
Contributor

@davidkhala davidkhala Jun 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean we transfer the responsibility to developer about how to visualize this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we should not be making that decision, this way they get the field as defined in the protobuf

} else {
throw new Error('unknown signature policy type');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deletion inspire me that, we suffer a lot like this.
There are some error handler which actually should be assertion, with cases rarely happen.
There are many error catcher simply return a message wrapping original error message, without taking original error stack into concern

For both case it is better to expose those fatal error to developer. instead of handle them as take it for granted

function decodeChaincodeID(proto_chaincode_id) {
function decodeResponse(responseProto) {
if (responseProto) {
const response = {};
Copy link
Contributor

@davidkhala davidkhala Jun 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const {status,message,payload } = responseProto
return {status,message,payload }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we could do that, we should do that with an overall clean up of this class

chaincode_id.path = proto_chaincode_id.getPath();
chaincode_id.name = proto_chaincode_id.getName();
chaincode_id.version = proto_chaincode_id.getVersion();
chaincode_id.path = chaincodeIDProto.path;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, or could we return the chaincodeIDProto directly? What else is inside that proto than these properties?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we could do that, we should do that with an overall clean up of this class

}

return range_query_info;
}

function decodeKVWrite(proto_kv_write) {
function decodeKVWrite(kVWriteProto) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we could do that, we should do that with an overall clean up of this class

Copy link
Contributor

@davidkhala davidkhala left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for this property access style instead of previous getter/setter

Verified

This commit was signed with the committer’s verified signature.
azu azu
Replace the grpc package with a pure javascript implementation.
The change involves changing the grpc message building and decoding.
Include and use the generated typescript for the protobufs.

Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
@bestbeforetoday bestbeforetoday merged commit d22e1a1 into hyperledger:master Jun 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants