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

Commit 797da09

Browse files
committed
[FAB-3421] SDK Go - Disconnect, RegisterBlockEvent
Change-Id: I891e42625ce7a0501605753abfcbcd0bdc161f46 Signed-off-by: Sandra Vrtikapa <sandra.vrtikapa@securekey.com>
1 parent ec9d2ef commit 797da09

File tree

3 files changed

+190
-14
lines changed

3 files changed

+190
-14
lines changed

fabric-client/events/eventhub.go

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package events
2222
import (
2323
"errors"
2424
"fmt"
25+
"reflect"
2526
"regexp"
2627
"sync"
2728

@@ -49,6 +50,9 @@ type EventHub interface {
4950
UnregisterChaincodeEvent(cbe *ChainCodeCBE)
5051
RegisterTxEvent(txID string, callback func(string, error))
5152
UnregisterTxEvent(txID string)
53+
RegisterBlockEvent(callback func(*common.Block))
54+
UnregisterBlockEvent(callback func(*common.Block))
55+
Disconnect()
5256
}
5357

5458
// The EventHubExt interface allows extensions of the SDK to add functionality to EventHub overloads.
@@ -130,8 +134,8 @@ func NewEventHub() EventHub {
130134
eventsClientFactory: &consumerClientFactory{},
131135
}
132136

133-
// default to listening for block events
134-
eventHub.SetInterests(true)
137+
// register default transaction callback
138+
eventHub.RegisterBlockEvent(eventHub.txCallback)
135139

136140
return eventHub
137141
}
@@ -141,12 +145,67 @@ func (eventHub *eventHub) SetInterests(block bool) {
141145
eventHub.mtx.Lock()
142146
defer eventHub.mtx.Unlock()
143147

144-
eventHub.interestedEvents = nil
148+
eventHub.interestedEvents = make([]*pb.Interest, 0)
149+
eventHub.blockRegistrants = make([]func(*common.Block), 0)
150+
145151
if block {
152+
eventHub.blockRegistrants = append(eventHub.blockRegistrants, eventHub.txCallback)
153+
eventHub.interestedEvents = append(eventHub.interestedEvents, &pb.Interest{EventType: pb.EventType_BLOCK})
154+
}
155+
}
156+
157+
// Disconnect disconnects from peer event source
158+
func (eventHub *eventHub) Disconnect() {
159+
if !eventHub.connected {
160+
return
161+
}
162+
163+
eventHub.mtx.Lock()
164+
defer eventHub.mtx.Unlock()
165+
166+
// Unregister interests with server and stop the stream
167+
eventHub.client.UnregisterAsync(eventHub.interestedEvents)
168+
eventHub.client.Stop()
169+
eventHub.connected = false
170+
}
171+
172+
// RegisterBlockEvent - register callback function for block events
173+
func (eventHub *eventHub) RegisterBlockEvent(callback func(*common.Block)) {
174+
eventHub.mtx.Lock()
175+
defer eventHub.mtx.Unlock()
176+
177+
eventHub.blockRegistrants = append(eventHub.blockRegistrants, callback)
178+
if len(eventHub.blockRegistrants) == 1 {
146179
eventHub.interestedEvents = append(eventHub.interestedEvents, &pb.Interest{EventType: pb.EventType_BLOCK})
147180
}
148181
}
149182

183+
// UnregisterBlockEvent unregister callback for block event
184+
func (eventHub *eventHub) UnregisterBlockEvent(callback func(*common.Block)) {
185+
eventHub.mtx.Lock()
186+
defer eventHub.mtx.Unlock()
187+
188+
f1 := reflect.ValueOf(callback)
189+
190+
for i := range eventHub.blockRegistrants {
191+
f2 := reflect.ValueOf(eventHub.blockRegistrants[i])
192+
if f1.Pointer() == f2.Pointer() {
193+
eventHub.blockRegistrants = append(eventHub.blockRegistrants[:i], eventHub.blockRegistrants[i+1:]...)
194+
break
195+
}
196+
}
197+
198+
if len(eventHub.blockRegistrants) < 1 {
199+
blockEventInterest := pb.Interest{EventType: pb.EventType_BLOCK}
200+
eventHub.client.UnregisterAsync([]*pb.Interest{&blockEventInterest})
201+
for i, v := range eventHub.interestedEvents {
202+
if *v == blockEventInterest {
203+
eventHub.interestedEvents = append(eventHub.interestedEvents[:i], eventHub.interestedEvents[i+1:]...)
204+
}
205+
}
206+
}
207+
}
208+
150209
// AddChaincodeInterest adds interest for specific CHAINCODE events.
151210
func (eventHub *eventHub) AddChaincodeInterest(ChaincodeID string, EventName string) {
152211
eventHub.interestedEvents = append(eventHub.interestedEvents, &pb.Interest{
@@ -191,24 +250,31 @@ func (eventHub *eventHub) IsConnected() bool {
191250
* Establishes connection with peer event source<p>
192251
*/
193252
func (eventHub *eventHub) Connect() error {
253+
254+
if eventHub.connected {
255+
logger.Debugf("Nothing to do - EventHub already connected")
256+
return nil
257+
}
258+
194259
if eventHub.peerAddr == "" {
195260
return fmt.Errorf("eventHub.peerAddr is empty")
196261
}
197262

198263
eventHub.mtx.Lock()
199264
defer eventHub.mtx.Unlock()
200265

201-
eventHub.blockRegistrants = make([]func(*common.Block), 0)
202-
eventHub.blockRegistrants = append(eventHub.blockRegistrants, eventHub.txCallback)
266+
if eventHub.client == nil {
267+
eventsClient, _ := eventHub.eventsClientFactory.newEventsClient(eventHub.peerAddr, eventHub.peerTLSCertificate, eventHub.peerTLSServerHostOverride, 5, eventHub)
268+
eventHub.client = eventsClient
269+
}
203270

204-
eventsClient, _ := eventHub.eventsClientFactory.newEventsClient(eventHub.peerAddr, eventHub.peerTLSCertificate, eventHub.peerTLSServerHostOverride, 5, eventHub)
205-
if err := eventsClient.Start(); err != nil {
206-
eventsClient.Stop()
271+
if err := eventHub.client.Start(); err != nil {
272+
eventHub.client.Stop()
207273
return fmt.Errorf("Error from eventsClient.Start (%s)", err.Error())
208-
209274
}
275+
210276
eventHub.connected = true
211-
eventHub.client = eventsClient
277+
212278
return nil
213279
}
214280

@@ -248,14 +314,15 @@ func (eventHub *eventHub) Recv(msg *pb.Event) (bool, error) {
248314
}
249315
}
250316

251-
// Disconnect implements consumer.EventAdapter interface for receiving events
252-
/**
253-
* Disconnects peer event source<p>
254-
*/
317+
// Disconnected implements consumer.EventAdapter interface for receiving events
255318
func (eventHub *eventHub) Disconnected(err error) {
256319
if !eventHub.connected {
257320
return
258321
}
322+
323+
eventHub.mtx.Lock()
324+
defer eventHub.mtx.Unlock()
325+
259326
eventHub.client.Stop()
260327
eventHub.connected = false
261328
}

fabric-client/events/eventhub_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import (
2727

2828
"time"
2929

30+
"reflect"
31+
32+
"github.com/hyperledger/fabric/protos/common"
3033
pb "github.com/hyperledger/fabric/protos/peer"
3134
)
3235

@@ -175,3 +178,53 @@ func flood(invocationsPerThread int, threads int, f func()) {
175178
}()
176179
}
177180
}
181+
182+
func TestRegisterBlockEvent(t *testing.T) {
183+
eventHub, _ := createMockedEventHub(t)
184+
if t.Failed() {
185+
return
186+
}
187+
188+
// Transaction callback is registered by default
189+
if len(eventHub.interestedEvents) != 1 || len(eventHub.blockRegistrants) != 1 {
190+
t.Fatalf("Transaction callback should be registered by default")
191+
}
192+
193+
f1 := reflect.ValueOf(eventHub.txCallback)
194+
f2 := reflect.ValueOf(eventHub.blockRegistrants[0])
195+
196+
if f1.Pointer() != f2.Pointer() {
197+
t.Fatalf("Registered callback is not txCallback")
198+
}
199+
200+
eventHub.RegisterBlockEvent(testCallback)
201+
202+
if len(eventHub.blockRegistrants) != 2 {
203+
t.Fatalf("Failed to add test callback for block event")
204+
}
205+
206+
f1 = reflect.ValueOf(testCallback)
207+
f2 = reflect.ValueOf(eventHub.blockRegistrants[1])
208+
209+
if f1.Pointer() != f2.Pointer() {
210+
t.Fatalf("Registered callback is not testCallback")
211+
}
212+
213+
eventHub.UnregisterBlockEvent(testCallback)
214+
215+
if len(eventHub.interestedEvents) != 1 || len(eventHub.blockRegistrants) != 1 {
216+
t.Fatalf("Failed to unregister testCallback")
217+
}
218+
219+
eventHub.UnregisterBlockEvent(eventHub.txCallback)
220+
221+
if len(eventHub.interestedEvents) != 0 || len(eventHub.blockRegistrants) != 0 {
222+
t.Fatalf("Failed to unregister txCallback")
223+
}
224+
225+
}
226+
227+
// private test callback to be executed on block event
228+
func testCallback(block *common.Block) {
229+
fmt.Println("testCallback called on block")
230+
}

test/integration/events_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ limitations under the License.
2020
package integration
2121

2222
import (
23+
"fmt"
2324
"testing"
2425
"time"
2526

2627
fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client"
2728
fcUtil "github.com/hyperledger/fabric-sdk-go/fabric-client/helpers"
29+
"github.com/hyperledger/fabric/protos/common"
2830
)
2931

3032
func TestEvents(t *testing.T) {
@@ -53,6 +55,19 @@ func TestEvents(t *testing.T) {
5355

5456
testFailedTx(t, testSetup)
5557

58+
// Test disconnect event hub
59+
testSetup.EventHub.Disconnect()
60+
if testSetup.EventHub.IsConnected() {
61+
t.Fatalf("Failed to disconnect event hub")
62+
}
63+
64+
// Reconnect event hub
65+
if err := testSetup.EventHub.Connect(); err != nil {
66+
t.Fatalf("Failed to connect event hub")
67+
}
68+
69+
testMultipleBlockEventCallbacks(t, testSetup)
70+
5671
}
5772

5873
func testFailedTx(t *testing.T, testSetup BaseSetupImpl) {
@@ -106,3 +121,44 @@ func testFailedTx(t *testing.T, testSetup BaseSetupImpl) {
106121
}
107122

108123
}
124+
125+
func testMultipleBlockEventCallbacks(t *testing.T, testSetup BaseSetupImpl) {
126+
127+
// Arguments for events CC
128+
var args []string
129+
args = append(args, "invoke")
130+
args = append(args, "invoke")
131+
args = append(args, "SEVERE")
132+
133+
// Create and register test callback that will be invoked upon block event
134+
test := make(chan bool)
135+
testSetup.EventHub.RegisterBlockEvent(func(block *common.Block) {
136+
fmt.Println("Invoked test callback on block event")
137+
test <- true
138+
})
139+
140+
tpResponses, tx, err := fcUtil.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()})
141+
if err != nil {
142+
t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err)
143+
}
144+
145+
// Register tx for commit/block event(s)
146+
done, fail := fcUtil.RegisterTxEvent(tx, testSetup.EventHub)
147+
defer testSetup.EventHub.UnregisterTxEvent(tx)
148+
149+
_, err = fcUtil.CreateAndSendTransaction(testSetup.Chain, tpResponses)
150+
if err != nil {
151+
t.Fatalf("First invoke failed err: %v", err)
152+
}
153+
154+
for i := 0; i < 2; i++ {
155+
select {
156+
case <-done:
157+
case <-fail:
158+
case <-test:
159+
case <-time.After(time.Second * 30):
160+
t.Fatalf("invoke Didn't receive test callback event")
161+
}
162+
}
163+
164+
}

0 commit comments

Comments
 (0)