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

Listen to private data in the events #154

Merged
merged 3 commits into from
Feb 19, 2022

Conversation

arsulegai
Copy link
Member

@arsulegai arsulegai commented Oct 26, 2021

Listen to the private data map from the deliver response message.
Addresses #153

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.

This approach looks generally OK to me. Please consider the specific review comments I have added an also:

  1. The BlockInfo class is a mashup of two (and now three) different behaviours depending on the event type it represents. This looks to me like BlockInfo should be an interface with three distinct (package private) implementation classes: FilteredBlockInfo, FullBlockInfo, PrivateBlockInfo (or if you prefer maybe BlockWithPrivateDataInfo). BlockInfo just describes the available methods and each implementation class holds only the logic for its block type and we lose all the convoluted if/else method implementations. This would mean BlockEvent should probably also be an interface (extending BlockInfo) with two distinct implementation classes: FullBlockEvent and PrivateBlockEvent. A factory method (on BlockEvent) can be used by the PeerEventServiceClient to create a suitable implementation instance based on the DeliverResponse type.
  2. Some tests are needed. I appreciate this code is not structured to make unit testing easy but you could modify or extend the existing integration testing of events to use the new private type.

@@ -1147,7 +1147,7 @@ public PeerOptions getPeersOptions(Peer peer) {
* @return old options.
*/

PeerOptions setPeerOptions(Peer peer, PeerOptions peerOptions) throws InvalidArgumentException {
public PeerOptions setPeerOptions(Peer peer, PeerOptions peerOptions) throws InvalidArgumentException {
Copy link
Member

Choose a reason for hiding this comment

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

This method is not currently exposed so I would prefer not to make it public unless absolutely necessary

Copy link
Member Author

Choose a reason for hiding this comment

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

Given that the peer options is a way to let the SDK request for private data. If one uses the SDK, they should have an ability to set the option. Is there a concern with this exposure?

Alternatives:

  1. Consider a new method to set the peer's block request type option explicitly.
  2. Consider a global setting at the channel level (instead of a peer option), to request generically private data from all the peers.
    Let me know your thoughts.

Copy link
Member

Choose a reason for hiding this comment

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

I’m not sure it is the way I would have designed the API but the suggested usage pattern can be seen here:

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the test case references. Otherwise, I was heading in the direction to reuse the channel instance created using the gateway SDK.

@@ -6416,11 +6416,12 @@ protected void finalize() throws Throwable {
protected Long startEvents;
protected Long stopEvents = Long.MAX_VALUE;
protected boolean registerEventsForFilteredBlocks = false;
protected boolean registerEventsForPrivateData = false;
Copy link
Member

Choose a reason for hiding this comment

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

A boolean worked when there were only two options but now there are three I think the event type would be better expressed with an enum. Something like:

public static class PeerOptions {
    public enum EventType {
        FILTERED, FULL, PRIVATE
    }

    private EventType eventType = EventType.FULL;

    public EventType getEventType() {
        return eventType;
    }

    public PeerOptions registerEventsForFilteredBlocks() {
        eventType = EventType.FILTERED;
        return this;
    }

    ...
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree

*
* @return true if private data blocks will be returned by the peer eventing service.
*/
public boolean isRegisterEventsForPrivateData() {
Copy link
Member

Choose a reason for hiding this comment

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

You could keep the isRegisterEventsForFilteredBlocks() method for backwards compatibility but this one wouldn't be necessary using an enum for the event type

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, agree.

@@ -59,6 +59,7 @@

private final PeerOptions peerOptions;
private final boolean filterBlock;
private final boolean blockAndPrivateData;
Copy link
Member

Choose a reason for hiding this comment

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

Similar to peer options, boolean worked as a toggle between two options but with three options I'd prefer to remove the booleans and use the enum described above

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, agree.

Comment on lines 312 to 313
nso = filterBlock ? broadcast.deliverFiltered(so) :
blockAndPrivateData ? broadcast.deliverWithPrivateData(so) : broadcast.deliver(so);
Copy link
Member

Choose a reason for hiding this comment

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

This would be clearer using an if/else on the event type enum value rather than nested ternary operators

Copy link
Member Author

Choose a reason for hiding this comment

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

Moved to switch on event type enum.

@arsulegai
Copy link
Member Author

Thanks @bestbeforetoday for the detailed review. These comments shows an encouraging sign and vindicates the approach in general. I will get the interfaces/enum added necessary to make the code better readable/cleaner.

@@ -31,6 +31,7 @@
import org.hyperledger.fabric.protos.peer.TransactionPackage;
import org.hyperledger.fabric.sdk.exception.InvalidProtocolBufferRuntimeException;
import org.hyperledger.fabric.sdk.transaction.ProtoUtils;
import sun.jvm.hotspot.utilities.AssertionFailure;
Copy link
Member

@bestbeforetoday bestbeforetoday Nov 12, 2021

Choose a reason for hiding this comment

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

This is failing the build and will prevent it running on non-Oracle/Sun JVMs, so this import cannot be used

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed. Error on my end, ignored the auto-IDE imports during commit.

@arsulegai
Copy link
Member Author

This approach looks generally OK to me. Please consider the specific review comments I have added an also:

  1. The BlockInfo class is a mashup of two (and now three) different behaviours depending on the event type it represents. This looks to me like BlockInfo should be an interface with three distinct (package private) implementation classes: FilteredBlockInfo, FullBlockInfo, PrivateBlockInfo (or if you prefer maybe BlockWithPrivateDataInfo). BlockInfo just describes the available methods and each implementation class holds only the logic for its block type and we lose all the convoluted if/else method implementations. This would mean BlockEvent should probably also be an interface (extending BlockInfo) with two distinct implementation classes: FullBlockEvent and PrivateBlockEvent. A factory method (on BlockEvent) can be used by the PeerEventServiceClient to create a suitable implementation instance based on the DeliverResponse type.
  2. Some tests are needed. I appreciate this code is not structured to make unit testing easy but you could modify or extend the existing integration testing of events to use the new private type.

Thanks for the feedback. I will continue refactoring for the point 1 in upcoming PRs. But extended an existing IT similar to other eventing test case for the private data.

Signed-off-by: S m, Aruna <aruna.mohan@walmart.com>
Signed-off-by: S m, Aruna <aruna.mohan@walmart.com>
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.

This change looks pretty good. Thank you for taking the time to rework it.

I had a look at whether it could be refactored to use inheritance or a strategy pattern to provide different implementations based on block event type instead of the cumbersome tests of type and different implementations within each method, but the code in this area looks to be so tangled that this would be a much larger piece of work. So I am happy with this pragmatic approach.

The one change I think might still be worth making is to avoid adding an isBlockAndPrivate() method, leaving the caller to figure out the block type by calling some combination of the is...() methods, and just go ahead and expose a type enum with a getType() method. I've made this change in the last commit on this branch in my fork. Have a look and, if it looks reasonable to you, go ahead and include that change in your PR so I can merge it.

- Expose enum for block event type instead of multiple boolean getters to determine event type.

Signed-off-by: Mark S. Lewis <mark_lewis@uk.ibm.com>
@arsulegai
Copy link
Member Author

@bestbeforetoday done. Cherry-picked your commit, thanks for helping out. I didn't want to assume why an exception was thrown in earlier case, thought of not breaking much.

On the first point to make this part of code more readable and to use better programming constructs, I am on it and will raise more PRs soon. It's taking some time and didn't want to block the pdc eventing capability until then.

It would also help if we can have a patch release with this feature.

@bestbeforetoday bestbeforetoday merged commit 44edbe5 into hyperledger:main Feb 19, 2022
bestbeforetoday added a commit to bestbeforetoday/fabric-sdk-java that referenced this pull request Feb 19, 2022
* Listen to private data in the events
* Add integration tests for the new PDC events feature
* Expose enum for block event type instead of multiple boolean getters to determine event type.

Signed-off-by: S m, Aruna <aruna.mohan@walmart.com>
Co-authored-by: Mark S. Lewis <mark_lewis@uk.ibm.com>
@arsulegai arsulegai deleted the pdc-events branch February 19, 2022 19:26
@bestbeforetoday
Copy link
Member

This is published in v2.2.12. Many thanks for the contribution!

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.

2 participants