Skip to content

Commit

Permalink
[FAB-9304]: Event Client GoDoc
Browse files Browse the repository at this point in the history
Change-Id: I1ff5114c7d64f6aa2d82f2e6c4b0b69d3b1786cc
Signed-off-by: Sandra Vrtikapa <[email protected]>
  • Loading branch information
sandrask committed Apr 3, 2018
1 parent 6b08f2e commit 5e8a2a1
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 29 deletions.
29 changes: 6 additions & 23 deletions pkg/client/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,12 @@ SPDX-License-Identifier: Apache-2.0

// Package event enables access to a channel events on a Fabric network. Event client receives events such as block, filtered block,
// chaincode, and transaction status events.
//
// // prepare channel client context
// org1ChannelClientContext := sdk.ChannelContext("mychannel", fabsdk.WithUser("User1"), fabsdk.WithOrg("Org1"))
//
// // create default event client (with filtered block events)
// eventClient, _ := event.New(org1ChannelClientContext)
// if err != nil {
// t.Fatalf("Failed to create new events client: %s", err)
// }
//
// // Register chaincode event (returns channel which receives event details when the event is complete)
// reg, notifier, err := eventClient.RegisterChaincodeEvent("eventcc", "event123")
// if err != nil {
// t.Fatalf("Failed to register cc event: %s", err)
// }
// defer eventClient.Unregister(reg)
//
// select {
// case ccEvent := <-notifier:
// t.Logf("Received cc event: %#v", ccEvent)
// case <-time.After(time.Second * 20):
// t.Fatalf("Did NOT receive CC event for 'event123'")
// }
// Basic Flow:
// 1) Prepare channel client context
// 2) Create event client
// 3) Register for events
// 4) Process events (or timeout)
// 5) Unregister
package event

import (
Expand Down
169 changes: 169 additions & 0 deletions pkg/client/event/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package event

import (
"fmt"
"time"

"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
)

func Example() {

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
fmt.Println("failed to create client")
}

registration, notifier, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

select {
case ccEvent := <-notifier:
fmt.Printf("received chaincode event %v", ccEvent)
case <-time.After(time.Second * 5):
fmt.Println("timeout while waiting for chaincode event")
}

// Timeout is expected since there is no event producer

// Output: timeout while waiting for chaincode event

}

func ExampleNew() {

ctx := mockChannelProvider("mychannel")

ec, err := New(ctx)
if err != nil {
fmt.Println(err)
}

ec, err = New(ctx, WithBlockEvents())
if err != nil {
fmt.Println(err)
}

if ec != nil {
fmt.Println("event client created")
} else {
fmt.Println("event client is nil")
}

// Output: event client created

}

func ExampleClient_RegisterChaincodeEvent() {

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

fmt.Println("chaincode event registered successfully")

// Output: chaincode event registered successfully

}

func ExampleClient_RegisterChaincodeEvent_withPayload() {

// If you require payload for chaincode events you have to use WithBlockEvents() option
ec, err := New(mockChannelProvider("mychannel"), WithBlockEvents())
if err != nil {
fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterChaincodeEvent("examplecc", "event123")
if err != nil {
fmt.Println("failed to register chaincode event")
}
defer ec.Unregister(registration)

fmt.Println("chaincode event registered successfully")

// Output: chaincode event registered successfully

}

func ExampleClient_RegisterTxStatusEvent() {

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterTxStatusEvent("tx123")
if err != nil {
fmt.Println("failed to register tx status event")
}
defer ec.Unregister(registration)

fmt.Println("tx status event registered successfully")

// Output: tx status event registered successfully

}

func ExampleClient_RegisterBlockEvent() {

ec, err := New(mockChannelProvider("mychannel"), WithBlockEvents())
if err != nil {
fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterBlockEvent()
if err != nil {
fmt.Println("failed to register block event")
}
defer ec.Unregister(registration)

fmt.Println("block event registered successfully")

// Output: block event registered successfully

}

func ExampleClient_RegisterFilteredBlockEvent() {

ec, err := New(mockChannelProvider("mychannel"))
if err != nil {
fmt.Println("failed to create client")
}

registration, _, err := ec.RegisterFilteredBlockEvent()
if err != nil {
fmt.Println("failed to register filtered block event")
}
defer ec.Unregister(registration)

fmt.Println("filtered block event registered successfully")

// Output: filtered block event registered successfully

}

func mockChannelProvider(channelID string) context.ChannelProvider {

channelProvider := func() (context.Channel, error) {
return mocks.NewMockChannel(channelID)
}

return channelProvider
}
3 changes: 2 additions & 1 deletion pkg/client/event/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ package event
// ClientOption describes a functional parameter for the New constructor
type ClientOption func(*Client) error

// WithBlockEvents option
// WithBlockEvents indicates that block events are to be received.
// Note that the caller must have sufficient privileges for this option.
func WithBlockEvents() ClientOption {
return func(c *Client) error {
c.permitBlockEvents = true
Expand Down
106 changes: 106 additions & 0 deletions pkg/fab/mocks/mockchannel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package mocks

import (
"github.com/pkg/errors"

"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp"
)

//Channel supplies the configuration for channel context client
type Channel struct {
context.Client
discovery fab.DiscoveryService
selection fab.SelectionService
channelService fab.ChannelService
channelID string
}

//Providers returns core providers
func (c *Channel) Providers() context.Client {
return c
}

//DiscoveryService returns discovery service
func (c *Channel) DiscoveryService() fab.DiscoveryService {
return c.discovery
}

//SelectionService returns selection service
func (c *Channel) SelectionService() fab.SelectionService {
return c.selection
}

//ChannelService returns channel service
func (c *Channel) ChannelService() fab.ChannelService {
return c.channelService
}

//ChannelID returns channel ID
func (c *Channel) ChannelID() string {
return c.channelID
}

type mockClientContext struct {
context.Providers
msp.SigningIdentity
}

//NewMockChannel creates new mock channel
func NewMockChannel(channelID string) (*Channel, error) {

ctx := &mockClientContext{
Providers: NewMockProviderContext(),
SigningIdentity: mspmocks.NewMockSigningIdentity("user", "user"),
}

// Set up mock channel service
chProvider, err := NewMockChannelProvider(ctx)
if err != nil {
return nil, errors.WithMessage(err, "new mock channel provider failed")
}
channelService, err := chProvider.ChannelService(ctx, channelID)
if err != nil {
return nil, errors.WithMessage(err, "failed to create mock channel service")
}

peers := []fab.Peer{NewMockPeer("Peer1", "http://peer1.com")}

// Set up mock discovery service
mockDiscovery, err := NewMockDiscoveryProvider(nil, peers)
if err != nil {
return nil, errors.WithMessage(err, "NewMockDiscoveryProvider failed")
}
discoveryService, err := mockDiscovery.CreateDiscoveryService(channelID)
if err != nil {
return nil, errors.WithMessage(err, "failed to create discovery service")
}

// Set up mock selection service
mockSelection, err := NewMockSelectionProvider(nil, peers)
if err != nil {
return nil, errors.WithMessage(err, "NewMockSelectinProvider failed")
}
selectionService, err := mockSelection.CreateSelectionService("mychannel")
if err != nil {
return nil, errors.WithMessage(err, "failed to create selection service")
}

channel := &Channel{
Client: ctx,
selection: selectionService,
discovery: discoveryService,
channelService: channelService,
channelID: channelID,
}

return channel, nil
}
20 changes: 17 additions & 3 deletions pkg/fab/mocks/mockeventservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,31 @@ func NewMockEventService() *MockEventService {

// RegisterBlockEvent registers for block events.
func (m *MockEventService) RegisterBlockEvent(filter ...fab.BlockFilter) (fab.Registration, <-chan *fab.BlockEvent, error) {
panic("not implemented")
eventCh := make(chan *fab.BlockEvent)
reg := &dispatcher.BlockReg{
Eventch: eventCh,
}
return reg, eventCh, nil
}

// RegisterFilteredBlockEvent registers for filtered block events.
func (m *MockEventService) RegisterFilteredBlockEvent() (fab.Registration, <-chan *fab.FilteredBlockEvent, error) {
panic("not implemented")
eventCh := make(chan *fab.FilteredBlockEvent)
reg := &dispatcher.FilteredBlockReg{
Eventch: eventCh,
}
return reg, eventCh, nil
}

// RegisterChaincodeEvent registers for chaincode events.
func (m *MockEventService) RegisterChaincodeEvent(ccID, eventFilter string) (fab.Registration, <-chan *fab.CCEvent, error) {
panic("not implemented")
eventCh := make(chan *fab.CCEvent)
reg := &dispatcher.ChaincodeReg{
Eventch: eventCh,
ChaincodeID: ccID,
EventFilter: eventFilter,
}
return reg, eventCh, nil
}

// RegisterTxStatusEvent registers for transaction status events.
Expand Down
4 changes: 2 additions & 2 deletions pkg/fabsdk/provider/fabpvdr/cachekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func NewCacheKey(ctx fab.ClientContext, chConfig fab.ChannelCfg, opts ...options
options.Apply(params, opts)

h := sha256.New()
h.Write(identity) // nolint
hash := h.Sum([]byte(chConfig.ID() + params.getOptKey()))
h.Write(append(identity, []byte(params.getOptKey())...)) // nolint
hash := h.Sum([]byte(chConfig.ID()))

return &CacheKey{
key: string(hash),
Expand Down

0 comments on commit 5e8a2a1

Please sign in to comment.