@@ -15,16 +15,18 @@ import (
1515 "testing"
1616 "time"
1717
18- "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/lbp "
18+ "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/peerresolver/preferorg "
1919
2020 "github.com/hyperledger/fabric-sdk-go/pkg/common/options"
2121 "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
2222 "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
2323 "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/api"
2424 "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/dispatcher"
25+ "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/lbp"
2526 clientmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/mocks"
2627 mockconn "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/mocks"
2728 "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/peerresolver/minblockheight"
29+ "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/client/peerresolver/preferpeer"
2830 esdispatcher "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/service/dispatcher"
2931 servicemocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/events/service/mocks"
3032 fabmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
@@ -1449,8 +1451,6 @@ func TestDisconnectIfBlockHeightLags(t *testing.T) {
14491451 conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx4" , pb .TxValidationCode_VALID ))
14501452 conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx5" , pb .TxValidationCode_VALID ))
14511453
1452- time .Sleep (time .Second )
1453-
14541454 // Set the block height of another peer to be greater than the disconnect threshold
14551455 // so that the event client can reconnect to another peer
14561456 p2 .SetBlockHeight (9 )
@@ -1463,6 +1463,152 @@ func TestDisconnectIfBlockHeightLags(t *testing.T) {
14631463 }
14641464}
14651465
1466+ // TestPreferLocalOrgConnection tests the scenario where an org wishes to connect to it's own peers
1467+ // if they are above the block height lag threshold but, if they fall below the threshold, the
1468+ // connection should be made to another org's peer. Once the local org's peers have caught up in
1469+ // block height, the connection to the local peer should be re-established.
1470+ func TestPreferLocalOrgConnection (t * testing.T ) {
1471+ channelID := "testchannel"
1472+ org1MSP := "Org1MSP"
1473+ org2MSP := "Org2MSP"
1474+ blockHeightLagThreshold := 2
1475+
1476+ p1O1 := clientmocks .NewMockStatefulPeer ("p1_o1" , "peer1.org1.com:7051" , clientmocks .WithMSP (org1MSP ), clientmocks .WithBlockHeight (4 ))
1477+ p2O1 := clientmocks .NewMockStatefulPeer ("p2_o1" , "peer2.org1.com:7051" , clientmocks .WithMSP (org1MSP ), clientmocks .WithBlockHeight (3 ))
1478+ p1O2 := clientmocks .NewMockStatefulPeer ("p1_o2" , "peer1.org2.com:7051" , clientmocks .WithMSP (org2MSP ), clientmocks .WithBlockHeight (10 ))
1479+ p2O2 := clientmocks .NewMockStatefulPeer ("p2_o2" , "peer1.org2.com:7051" , clientmocks .WithMSP (org2MSP ), clientmocks .WithBlockHeight (11 ))
1480+
1481+ connectch := make (chan * dispatcher.ConnectionEvent )
1482+
1483+ conn := clientmocks .NewMockConnection (
1484+ clientmocks .WithLedger (servicemocks .NewMockLedger (servicemocks .FilteredBlockEventFactory , sourceURL )),
1485+ )
1486+ connectionProvider := clientmocks .NewProviderFactory ().Provider (conn )
1487+
1488+ eventClient , _ , err := newClientWithMockConnAndOpts (
1489+ fabmocks .NewMockContext (
1490+ mspmocks .NewMockSigningIdentity ("user1" , "Org1MSP" ),
1491+ ),
1492+ fabmocks .NewMockChannelCfg (channelID ),
1493+ clientmocks .NewDiscoveryService (p1O1 , p2O1 , p1O2 , p2O2 ),
1494+ connectionProvider , filteredClientProvider ,
1495+ []options.Opt {
1496+ esdispatcher .WithEventConsumerTimeout (3 * time .Second ),
1497+ WithMaxConnectAttempts (1 ),
1498+ WithTimeBetweenConnectAttempts (time .Millisecond ),
1499+ WithConnectionEvent (connectch ),
1500+ WithResponseTimeout (2 * time .Second ),
1501+ dispatcher .WithPeerResolver (preferorg .NewResolver ()),
1502+ dispatcher .WithLoadBalancePolicy (lbp .NewRoundRobin ()),
1503+ dispatcher .WithPeerMonitorPeriod (250 * time .Millisecond ),
1504+ minblockheight .WithBlockHeightLagThreshold (blockHeightLagThreshold ),
1505+ minblockheight .WithReconnectBlockHeightThreshold (3 ),
1506+ },
1507+ )
1508+ require .NoErrorf (t , err , "error creating channel event client" )
1509+ err = eventClient .Connect ()
1510+ require .NoErrorf (t , err , "errorconnecting channel event client" )
1511+ defer eventClient .Close ()
1512+
1513+ connectedPeer := eventClient .Dispatcher ().(* dispatcher.Dispatcher ).ConnectedPeer ()
1514+ assert .Equal (t , org2MSP , connectedPeer .MSPID ())
1515+
1516+ outcomech := make (chan mockconn.Outcome )
1517+ go listenConnection (connectch , outcomech )
1518+
1519+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx1" , pb .TxValidationCode_VALID ))
1520+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx2" , pb .TxValidationCode_VALID ))
1521+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx3" , pb .TxValidationCode_VALID ))
1522+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx4" , pb .TxValidationCode_VALID ))
1523+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx5" , pb .TxValidationCode_VALID ))
1524+
1525+ // Set the block height of the local peer to be greater than the disconnect threshold
1526+ // so that the event client can reconnect to the local peer
1527+ p2O1 .SetBlockHeight (9 )
1528+
1529+ select {
1530+ case outcome := <- outcomech :
1531+ assert .Equal (t , mockconn .ReconnectedOutcome , outcome )
1532+ connectedPeer := eventClient .Dispatcher ().(* dispatcher.Dispatcher ).ConnectedPeer ()
1533+ assert .Equal (t , org1MSP , connectedPeer .MSPID ())
1534+ case <- time .After (3 * time .Second ):
1535+ t .Fatal ("Timed out waiting for reconnect" )
1536+ }
1537+ }
1538+
1539+ // TestPreferLocalPeersConnection tests the scenario where an org wishes to connect to one of a list of preferred peers
1540+ // if they are above the block height lag threshold but, if they fall below the threshold, the
1541+ // connection should be made to another peer. Once the preferred peers have caught up in
1542+ // block height, the connection to one of the preferred peers should be re-established.
1543+ func TestPreferLocalPeersConnection (t * testing.T ) {
1544+ channelID := "testchannel"
1545+ org1MSP := "Org1MSP"
1546+ org2MSP := "Org2MSP"
1547+ blockHeightLagThreshold := 2
1548+
1549+ p1O1 := clientmocks .NewMockStatefulPeer ("p1_o1" , "peer1.org1.com:7051" , clientmocks .WithMSP (org1MSP ), clientmocks .WithBlockHeight (4 ))
1550+ p2O1 := clientmocks .NewMockStatefulPeer ("p2_o1" , "peer2.org1.com:7051" , clientmocks .WithMSP (org1MSP ), clientmocks .WithBlockHeight (3 ))
1551+ p1O2 := clientmocks .NewMockStatefulPeer ("p1_o2" , "peer1.org2.com:7051" , clientmocks .WithMSP (org2MSP ), clientmocks .WithBlockHeight (10 ))
1552+ p2O2 := clientmocks .NewMockStatefulPeer ("p2_o2" , "peer1.org2.com:7051" , clientmocks .WithMSP (org2MSP ), clientmocks .WithBlockHeight (11 ))
1553+
1554+ connectch := make (chan * dispatcher.ConnectionEvent )
1555+
1556+ conn := clientmocks .NewMockConnection (
1557+ clientmocks .WithLedger (servicemocks .NewMockLedger (servicemocks .FilteredBlockEventFactory , sourceURL )),
1558+ )
1559+ connectionProvider := clientmocks .NewProviderFactory ().Provider (conn )
1560+
1561+ eventClient , _ , err := newClientWithMockConnAndOpts (
1562+ fabmocks .NewMockContext (
1563+ mspmocks .NewMockSigningIdentity ("user1" , "Org1MSP" ),
1564+ ),
1565+ fabmocks .NewMockChannelCfg (channelID ),
1566+ clientmocks .NewDiscoveryService (p1O1 , p2O1 , p1O2 , p2O2 ),
1567+ connectionProvider , filteredClientProvider ,
1568+ []options.Opt {
1569+ esdispatcher .WithEventConsumerTimeout (3 * time .Second ),
1570+ WithMaxConnectAttempts (1 ),
1571+ WithTimeBetweenConnectAttempts (time .Millisecond ),
1572+ WithConnectionEvent (connectch ),
1573+ WithResponseTimeout (2 * time .Second ),
1574+ dispatcher .WithPeerResolver (preferpeer .NewResolver (p1O1 .URL (), p2O1 .URL ())),
1575+ dispatcher .WithLoadBalancePolicy (lbp .NewRoundRobin ()),
1576+ dispatcher .WithPeerMonitorPeriod (250 * time .Millisecond ),
1577+ minblockheight .WithBlockHeightLagThreshold (blockHeightLagThreshold ),
1578+ minblockheight .WithReconnectBlockHeightThreshold (3 ),
1579+ },
1580+ )
1581+ require .NoErrorf (t , err , "error creating channel event client" )
1582+ err = eventClient .Connect ()
1583+ require .NoErrorf (t , err , "errorconnecting channel event client" )
1584+ defer eventClient .Close ()
1585+
1586+ connectedPeer := eventClient .Dispatcher ().(* dispatcher.Dispatcher ).ConnectedPeer ()
1587+ assert .Equal (t , org2MSP , connectedPeer .MSPID ())
1588+
1589+ outcomech := make (chan mockconn.Outcome )
1590+ go listenConnection (connectch , outcomech )
1591+
1592+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx1" , pb .TxValidationCode_VALID ))
1593+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx2" , pb .TxValidationCode_VALID ))
1594+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx3" , pb .TxValidationCode_VALID ))
1595+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx4" , pb .TxValidationCode_VALID ))
1596+ conn .Ledger ().NewFilteredBlock (channelID , servicemocks .NewFilteredTx ("tx5" , pb .TxValidationCode_VALID ))
1597+
1598+ // Set the block height of the local peer to be greater than the disconnect threshold
1599+ // so that the event client can reconnect to the local peer
1600+ p2O1 .SetBlockHeight (9 )
1601+
1602+ select {
1603+ case outcome := <- outcomech :
1604+ assert .Equal (t , mockconn .ReconnectedOutcome , outcome )
1605+ connectedPeer := eventClient .Dispatcher ().(* dispatcher.Dispatcher ).ConnectedPeer ()
1606+ assert .Equal (t , org1MSP , connectedPeer .MSPID ())
1607+ case <- time .After (3 * time .Second ):
1608+ t .Fatal ("Timed out waiting for reconnect" )
1609+ }
1610+ }
1611+
14661612func TestTransferRegistrations (t * testing.T ) {
14671613 // Tests the scenario where all event registrations are transferred to another event client.
14681614 t .Run ("Transfer" , func (t * testing.T ) {
0 commit comments