Skip to content

Commit

Permalink
[FAB-6385] Go SDK Configurable timeouts
Browse files Browse the repository at this point in the history
Change-Id: I9558396750f95e81dc0d00226f59214df5861cb4
Signed-off-by: Sudesh Shetty <sudesh.shetty@securekey.com>
  • Loading branch information
sudeshrshetty committed Oct 2, 2017
1 parent 2578687 commit 20ff232
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 73 deletions.
24 changes: 15 additions & 9 deletions api/apiconfig/configprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Config interface {
CAServerCertFiles(org string) ([]string, error)
CAClientKeyFile(org string) (string, error)
CAClientCertFile(org string) (string, error)
TimeoutOrDefault(ConnectionType) time.Duration
TimeoutOrDefault(TimeoutType) time.Duration
MspID(org string) (string, error)
OrderersConfig() ([]OrdererConfig, error)
RandomOrdererConfig() (*OrdererConfig, error)
Expand All @@ -47,16 +47,22 @@ type Config interface {
CSPConfig() *bccspFactory.FactoryOpts
}

// ConnectionType enumerates the different types of outgoing connections
type ConnectionType int
// TimeoutType enumerates the different types of outgoing connections
type TimeoutType int

const (
// Endorser connection
Endorser ConnectionType = iota
// EventHub connection
// Endorser connection timeout
Endorser TimeoutType = iota
// EventHub connection timeout
EventHub
// EventReg connection
// EventReg connection timeout
EventReg
// Orderer connection
Orderer
// Query timeout
Query
// ExecuteTx timeout
ExecuteTx
// OrdererConnection Orderer connection timeout
OrdererConnection
// OrdererSendDeliver Orderer SendDeliver timeout
OrdererResponse
)
2 changes: 1 addition & 1 deletion api/apiconfig/mocks/mockconfig.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 12 additions & 6 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,23 @@ func (c *Config) CAClientCertFile(org string) (string, error) {
}

// TimeoutOrDefault reads connection timeouts for the given connection type
func (c *Config) TimeoutOrDefault(conn apiconfig.ConnectionType) time.Duration {
func (c *Config) TimeoutOrDefault(conn apiconfig.TimeoutType) time.Duration {
var timeout time.Duration
switch conn {
case apiconfig.Endorser:
timeout = myViper.GetDuration("client.connection.timeout.peer.endorser")
timeout = myViper.GetDuration("client.endorserConnectionTimeout")
case apiconfig.EventHub:
timeout = myViper.GetDuration("client.connection.timeout.peer.eventhub")
timeout = myViper.GetDuration("client.eventServiceConnectionTimeout")
case apiconfig.EventReg:
timeout = myViper.GetDuration("client.connection.timeout.peer.eventreg")
case apiconfig.Orderer:
timeout = myViper.GetDuration("client.connection.timeout.orderer")
timeout = myViper.GetDuration("client.eventRegistrationResponseTimeout")
case apiconfig.OrdererConnection:
timeout = myViper.GetDuration("client.ordererConnectionTimeout")
case apiconfig.Query:
timeout = myViper.GetDuration("client.queryResponseTimeout")
case apiconfig.ExecuteTx:
timeout = myViper.GetDuration("client.executeTxResponseTimeout")
case apiconfig.OrdererResponse:
timeout = myViper.GetDuration("client.ordererResponseTimeout")
}
if timeout == 0 {
timeout = defaultTimeout
Expand Down
27 changes: 18 additions & 9 deletions pkg/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,7 @@ client:
logging:
level: info

# set connection timeouts for the peer and orderer for the client
connection:
timeout:
peer:
endorser: 3s
eventHub: 3s
eventReg: 3s
orderer: 3s


# Needed to load users crypto keys and certs.
cryptoconfig:
Expand Down Expand Up @@ -94,6 +87,22 @@ client:
#library: "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so, /usr/lib/softhsm/libsofthsm2.so ,/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so, /usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so, /usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so"
library: "add BCCSP library here"

#Timeout configs for various connection and response types
endorserConnectionTimeout: 3s

eventServiceConnectionTimeout: 3s

ordererConnectionTimeout: 3s

ordererResponseTimeout: 5s

eventRegistrationResponseTimeout: 3s

queryResponseTimeout: 20s

executeTxResponseTimeout: 30s


#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
Expand Down Expand Up @@ -233,7 +242,7 @@ certificateAuthorities:
# Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
# needed to enroll and invoke new users.
# registrar:
# enrollId: usualy-it-is_admin
# enrollId: usually-it-is_admin
# enrollSecret: adminpasswd
# [Optional] The optional name of the CA.
# caName: ca-org1
51 changes: 34 additions & 17 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,33 +300,50 @@ func TestTLSACAConfig(t *testing.T) {
}

func TestTimeouts(t *testing.T) {
myViper.Set("client.connection.timeout.peer.endorser", "2s")
myViper.Set("client.connection.timeout.peer.eventhub", "2m")
myViper.Set("client.connection.timeout.peer.eventreg", "2h")
myViper.Set("client.connection.timeout.orderer", "2ms")
myViper.Set("client.endorserConnectionTimeout", "2s")
myViper.Set("client.eventServiceConnectionTimeout", "2m")
myViper.Set("client.eventRegistrationResponseTimeout", "2h")
myViper.Set("client.ordererConnectionTimeout", "2ms")
myViper.Set("client.queryResponseTimeout", "7h")
myViper.Set("client.executeTxResponseTimeout", "8h")
myViper.Set("client.ordererResponseTimeout", "6s")

t1 := configImpl.TimeoutOrDefault(api.Endorser)
if t1 != time.Second*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t2 := configImpl.TimeoutOrDefault(api.EventHub)
if t2 != time.Minute*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t2)
t1 = configImpl.TimeoutOrDefault(api.EventHub)
if t1 != time.Minute*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t1 = configImpl.TimeoutOrDefault(api.EventReg)
if t1 != time.Hour*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t1 = configImpl.TimeoutOrDefault(api.Query)
if t1 != time.Hour*7 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t1 = configImpl.TimeoutOrDefault(api.ExecuteTx)
if t1 != time.Hour*8 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t3 := configImpl.TimeoutOrDefault(api.EventReg)
if t3 != time.Hour*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t3)
t1 = configImpl.TimeoutOrDefault(api.OrdererConnection)
if t1 != time.Millisecond*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}
t4 := configImpl.TimeoutOrDefault(api.Orderer)
if t4 != time.Millisecond*2 {
t.Fatalf("Timeout not read correctly. Got: %s", t4)
t1 = configImpl.TimeoutOrDefault(api.OrdererResponse)
if t1 != time.Second*6 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}

// Test default
myViper.Set("client.connection.timeout.orderer", "")
t5 := configImpl.TimeoutOrDefault(api.Orderer)
if t5 != time.Second*5 {
t.Fatalf("Timeout not read correctly. Got: %s", t5)
myViper.Set("client.ordererConnectionTimeout", "")
t1 = configImpl.TimeoutOrDefault(api.OrdererConnection)
if t1 != time.Second*5 {
t.Fatalf("Timeout not read correctly. Got: %s", t1)
}

}

func TestOrdererConfig(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/fabric-ca-client/mocks/mockconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (c *MockConfig) FabricClientViper() *viper.Viper {
}

//TimeoutOrDefault not implemented
func (c *MockConfig) TimeoutOrDefault(apiconfig.ConnectionType) time.Duration {
func (c *MockConfig) TimeoutOrDefault(apiconfig.TimeoutType) time.Duration {
return 0
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/fabric-client/channel/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package channel
import (
"fmt"

config "github.com/hyperledger/fabric-sdk-go/api/apiconfig"
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp"
Expand All @@ -35,6 +36,7 @@ type ClientContext interface {
UserContext() fab.User
SigningManager() fab.SigningManager
NewTxnID() (apitxn.TransactionID, error)
Config() config.Config
}

// NewChannel represents a channel in a Fabric network.
Expand Down
3 changes: 2 additions & 1 deletion pkg/fabric-client/channel/txnsender.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
protos_utils "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/protos/utils"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal/txnproc"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
Expand Down Expand Up @@ -390,7 +391,7 @@ func (c *Channel) SendEnvelope(envelope *fab.SignedEnvelope) (*common.Block, err
}
mutex.Unlock()

case <-time.After(time.Second * 5):
case <-time.After(c.ClientContext().Config().TimeoutOrDefault(apiconfig.OrdererResponse)):
mutex.Lock()
if errorResponse == nil {
errorResponse = fmt.Errorf("Timeout waiting for response from orderer")
Expand Down
6 changes: 5 additions & 1 deletion pkg/fabric-client/mocks/mockconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ func (c *MockConfig) CAClientCertFile(org string) (string, error) {
}

//TimeoutOrDefault not implemented
func (c *MockConfig) TimeoutOrDefault(config.ConnectionType) time.Duration {
func (c *MockConfig) TimeoutOrDefault(arg config.TimeoutType) time.Duration {

if arg == config.Query || arg == config.ExecuteTx {
return time.Second * 10
}
return 0
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/fabric-client/orderer/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Orderer struct {
// NewOrderer Returns a Orderer instance
func NewOrderer(url string, certificate string, serverHostOverride string, config apiconfig.Config) (*Orderer, error) {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTimeout(config.TimeoutOrDefault(apiconfig.Orderer)))
opts = append(opts, grpc.WithTimeout(config.TimeoutOrDefault(apiconfig.OrdererConnection)))
if config.IsTLSEnabled() {
tlsCaCertPool, err := config.TLSCACertPool(certificate)
if err != nil {
Expand Down
14 changes: 5 additions & 9 deletions pkg/fabric-txn/chclient/chclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,14 @@ import (
"reflect"
"time"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/internal"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
)

const (
defaultQueryTimeout = time.Second * 20
defaultExecuteTxTimeout = time.Second * 30
)

// ChannelClient enables access to a Fabric network.
type ChannelClient struct {
client fab.FabricClient
Expand All @@ -43,7 +39,7 @@ func NewChannelClient(client fab.FabricClient, channel fab.Channel, discovery fa
// Query chaincode
func (cc *ChannelClient) Query(request apitxn.QueryRequest) ([]byte, error) {

return cc.QueryWithOpts(request, apitxn.QueryOpts{Timeout: defaultQueryTimeout})
return cc.QueryWithOpts(request, apitxn.QueryOpts{})

}

Expand Down Expand Up @@ -72,7 +68,7 @@ func (cc *ChannelClient) QueryWithOpts(request apitxn.QueryRequest, opts apitxn.
return nil, nil
}

timeout := defaultQueryTimeout
timeout := cc.client.Config().TimeoutOrDefault(apiconfig.Query)
if opts.Timeout != 0 {
timeout = opts.Timeout
}
Expand Down Expand Up @@ -106,7 +102,7 @@ func sendTransactionProposal(request apitxn.QueryRequest, channel fab.Channel, p
// ExecuteTx prepares and executes transaction
func (cc *ChannelClient) ExecuteTx(request apitxn.ExecuteTxRequest) (apitxn.TransactionID, error) {

return cc.ExecuteTxWithOpts(request, apitxn.ExecuteTxOpts{Timeout: defaultExecuteTxTimeout})
return cc.ExecuteTxWithOpts(request, apitxn.ExecuteTxOpts{})
}

// ExecuteTxWithOpts allows the user to provide options for execute transaction:
Expand Down Expand Up @@ -142,7 +138,7 @@ func (cc *ChannelClient) ExecuteTxWithOpts(request apitxn.ExecuteTxRequest, opts
notifier = make(chan apitxn.ExecuteTxResponse)
}

timeout := defaultExecuteTxTimeout
timeout := cc.client.Config().TimeoutOrDefault(apiconfig.ExecuteTx)
if opts.Timeout != 0 {
timeout = opts.Timeout
}
Expand Down
23 changes: 14 additions & 9 deletions test/fixtures/config/config_pkcs11_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,6 @@ client:
logging:
level: info

# set connection timeouts for the peer and orderer for the client
connection:
timeout:
peer:
endorser: 3s
eventHub: 3s
eventReg: 3s
orderer: 3s

# Needed to load users crypto keys and certs.
cryptoconfig:
path: $GOPATH/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/channel/crypto-config
Expand Down Expand Up @@ -89,6 +80,20 @@ client:
label: "ForFabric"
library: "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so, /usr/lib/softhsm/libsofthsm2.so ,/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so, /usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so, /usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so"

#Timeout configs for various connection and response types
endorserConnectionTimeout: 3s

eventServiceConnectionTimeout: 3s

ordererConnectionTimeout: 3s

ordererResponseTimeout: 5s

eventRegistrationResponseTimeout: 3s

queryResponseTimeout: 20s

executeTxResponseTimeout: 30s
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
Expand Down
23 changes: 14 additions & 9 deletions test/fixtures/config/config_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ client:
logging:
level: info

# set connection timeouts for the peer and orderer for the client
connection:
timeout:
peer:
endorser: 3s
eventHub: 3s
eventReg: 3s
orderer: 3s

# Needed to load users crypto keys and certs.
cryptoconfig:
path: $GOPATH/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/channel/crypto-config
Expand Down Expand Up @@ -87,6 +78,20 @@ client:
ephemeral: false
level: 256

#Timeout configs for various connection and response types
endorserConnectionTimeout: 3s

eventServiceConnectionTimeout: 3s

ordererConnectionTimeout: 3s

ordererResponseTimeout: 5s

eventRegistrationResponseTimeout: 3s

queryResponseTimeout: 20s

executeTxResponseTimeout: 30s
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
Expand Down

0 comments on commit 20ff232

Please sign in to comment.