Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 948f2fd

Browse files
bstasyszyntroyronda
authored andcommitted
[FAB-8395] Abstract Event Service
Defined an Event Service API and provided an abstract implementation which may be reused by protocol-specific implementations (e.g. Event Hub and Deliver Service) Change-Id: Ie8b901dfe08df20b01a38ba26c85a3a87f667a41 Signed-off-by: Bob Stasyszyn <Bob.Stasyszyn@securekey.com>
1 parent 05b5ab9 commit 948f2fd

File tree

19 files changed

+3152
-0
lines changed

19 files changed

+3152
-0
lines changed

api/apifabclient/eventservice.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package apifabclient
8+
9+
import (
10+
cb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
11+
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
12+
)
13+
14+
// BlockEvent contains the data for the block event
15+
type BlockEvent struct {
16+
Block *cb.Block
17+
}
18+
19+
// FilteredBlockEvent contains the data for a filtered block event
20+
type FilteredBlockEvent struct {
21+
FilteredBlock *pb.FilteredBlock
22+
}
23+
24+
// TxStatusEvent contains the data for a transaction status event
25+
type TxStatusEvent struct {
26+
TxID string
27+
TxValidationCode pb.TxValidationCode
28+
}
29+
30+
// CCEvent contains the data for a chaincode event
31+
type CCEvent struct {
32+
TxID string
33+
ChaincodeID string
34+
EventName string
35+
}
36+
37+
// Registration is a handle that is returned from a successful RegisterXXXEvent.
38+
// This handle should be used in Unregister in order to unregister the event.
39+
type Registration interface{}
40+
41+
// BlockFilter is a function that determines whether a Block event
42+
// should be ignored
43+
type BlockFilter func(block *cb.Block) bool
44+
45+
// EventService is a service that receives events such as block, filtered block,
46+
// chaincode, and transaction status events.
47+
type EventService interface {
48+
// RegisterBlockEvent registers for block events. If the caller does not have permission
49+
// to register for block events then an error is returned.
50+
// Note that Unregister must be called when the registration is no longer needed.
51+
// - filter is an optional filter that filters out unwanted events. (Note: Only one filter may be specified.)
52+
// - Returns the registration and a channel that is used to receive events. The channel
53+
// is closed when Unregister is called.
54+
RegisterBlockEvent(filter ...BlockFilter) (Registration, <-chan *BlockEvent, error)
55+
56+
// RegisterFilteredBlockEvent registers for filtered block events.
57+
// Note that Unregister must be called when the registration is no longer needed.
58+
// - Returns the registration and a channel that is used to receive events. The channel
59+
// is closed when Unregister is called.
60+
RegisterFilteredBlockEvent() (Registration, <-chan *FilteredBlockEvent, error)
61+
62+
// RegisterChaincodeEvent registers for chaincode events.
63+
// Note that Unregister must be called when the registration is no longer needed.
64+
// - ccID is the chaincode ID for which events are to be received
65+
// - eventFilter is the chaincode event filter (regular expression) for which events are to be received
66+
// - Returns the registration and a channel that is used to receive events. The channel
67+
// is closed when Unregister is called.
68+
RegisterChaincodeEvent(ccID, eventFilter string) (Registration, <-chan *CCEvent, error)
69+
70+
// RegisterTxStatusEvent registers for transaction status events.
71+
// Note that Unregister must be called when the registration is no longer needed.
72+
// - txID is the transaction ID for which events are to be received
73+
// - Returns the registration and a channel that is used to receive events. The channel
74+
// is closed when Unregister is called.
75+
RegisterTxStatusEvent(txID string) (Registration, <-chan *TxStatusEvent, error)
76+
77+
// Unregister removes the given registration and closes the event channel.
78+
// - reg is the registration handle that was returned from one of the Register functions
79+
Unregister(reg Registration)
80+
}
81+
82+
// EventClient is a client that connects to a peer and receives channel events
83+
// such as block, filtered block, chaincode, and transaction status events.
84+
type EventClient interface {
85+
EventService
86+
87+
// Connect connects to the event server.
88+
Connect() error
89+
90+
// Close closes the connection to the event server and releases all resources.
91+
// Once this function is invoked the client may no longer be used.
92+
Close()
93+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package blockfilter
8+
9+
import (
10+
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
11+
cb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
12+
)
13+
14+
// AcceptAny returns a block filter that accepts any block
15+
var AcceptAny apifabclient.BlockFilter = func(block *cb.Block) bool {
16+
return true
17+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package headertypefilter
8+
9+
import (
10+
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
11+
"github.com/hyperledger/fabric-sdk-go/pkg/logging"
12+
cb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
13+
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/utils"
14+
)
15+
16+
var logger = logging.NewLogger("eventservice/blockfilter")
17+
18+
// New returns a block filter that filters out blocks that
19+
// don't contain envelopes of the given type(s)
20+
func New(headerTypes ...cb.HeaderType) apifabclient.BlockFilter {
21+
return func(block *cb.Block) bool {
22+
return hasType(block, headerTypes...)
23+
}
24+
}
25+
26+
func hasType(block *cb.Block, headerTypes ...cb.HeaderType) bool {
27+
for i := 0; i < len(block.Data.Data); i++ {
28+
env, err := utils.ExtractEnvelope(block, i)
29+
if err != nil {
30+
logger.Errorf("error extracting envelope from block: %s", err)
31+
continue
32+
}
33+
payload, err := utils.ExtractPayload(env)
34+
if err != nil {
35+
logger.Errorf("error extracting payload from block: %s", err)
36+
continue
37+
}
38+
chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
39+
if err != nil {
40+
logger.Errorf("error extracting channel header: %s", err)
41+
continue
42+
}
43+
htype := cb.HeaderType(chdr.Type)
44+
for _, headerType := range headerTypes {
45+
if htype == headerType {
46+
return true
47+
}
48+
}
49+
}
50+
return false
51+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package headertypefilter
8+
9+
import (
10+
"testing"
11+
12+
servicemocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/events/service/mocks"
13+
cb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
14+
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
15+
)
16+
17+
func TestHeaderTypeBlockFilter(t *testing.T) {
18+
filter := New(cb.HeaderType_CONFIG, cb.HeaderType_CONFIG_UPDATE)
19+
20+
if !filter(servicemocks.NewBlock("somechannel", servicemocks.NewTransaction("txid", pb.TxValidationCode_VALID, cb.HeaderType_CONFIG))) {
21+
t.Fatalf("expecting block filter to accept block with header type %s", cb.HeaderType_CONFIG)
22+
}
23+
if !filter(servicemocks.NewBlock("somechannel", servicemocks.NewTransaction("txid", pb.TxValidationCode_VALID, cb.HeaderType_CONFIG_UPDATE))) {
24+
t.Fatalf("expecting block filter to accept block with header type %s", cb.HeaderType_CONFIG_UPDATE)
25+
}
26+
if filter(servicemocks.NewBlock("somechannel", servicemocks.NewTransaction("txid", pb.TxValidationCode_VALID, cb.HeaderType_MESSAGE))) {
27+
t.Fatalf("expecting block filter to reject block with header type %s", cb.HeaderType_MESSAGE)
28+
}
29+
}

0 commit comments

Comments
 (0)