From f5bfb4c3aae133a8738ce82f6d767261f3f58f35 Mon Sep 17 00:00:00 2001 From: Bob Stasyszyn Date: Thu, 19 Dec 2019 13:02:38 -0500 Subject: [PATCH] [FABG-929] Use retry options from channel policy for selection (#36) The retry options for the Fabric selection service are now retrieved from the Discovery channel policies which are defined in the channel config. Also added default retry options in case the config file does not define any. Signed-off-by: Bob Stasyszyn --- go.mod | 1 - .../fabricselection/fabricselection.go | 25 +++++-------------- pkg/fab/default_channel_test.go | 4 +++ pkg/fab/endpointconfig.go | 25 ++++++++++++++++++- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 768efa7fe1..1ac9e107f8 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,6 @@ require ( github.com/stretchr/testify v1.3.0 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/net v0.0.0-20190311183353-d8887717615a - google.golang.org/appengine v1.4.0 // indirect google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d // indirect google.golang.org/grpc v1.23.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect diff --git a/pkg/client/common/selection/fabricselection/fabricselection.go b/pkg/client/common/selection/fabricselection/fabricselection.go index 166b4d8ec6..e70d66a8cd 100644 --- a/pkg/client/common/selection/fabricselection/fabricselection.go +++ b/pkg/client/common/selection/fabricselection/fabricselection.go @@ -29,7 +29,6 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache" "github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref" "github.com/pkg/errors" - grpcCodes "google.golang.org/grpc/codes" ) const ( @@ -41,23 +40,6 @@ const ( var logger = logging.NewLogger(moduleName) -var retryableCodes = map[status.Group][]status.Code{ - status.GRPCTransportStatus: { - status.Code(grpcCodes.Unavailable), - }, - status.DiscoveryServerStatus: { - status.QueryEndorsers, - }, -} - -var defaultRetryOpts = retry.Opts{ - Attempts: 6, - InitialBackoff: 500 * time.Millisecond, - MaxBackoff: 5 * time.Second, - BackoffFactor: 1.75, - RetryableCodes: retryableCodes, -} - // DiscoveryClient is the client to the discovery service type DiscoveryClient interface { Send(ctx context.Context, req *fabdiscovery.Request, targets ...fab.PeerConfig) ([]fabdiscovery.Response, error) @@ -84,7 +66,8 @@ type Service struct { // New creates a new dynamic selection service using Fabric's Discovery Service func New(ctx contextAPI.Client, channelID string, discovery fab.DiscoveryService, opts ...coptions.Opt) (*Service, error) { - options := params{retryOpts: defaultRetryOpts} + options := params{retryOpts: getDefaultRetryOpts(ctx, channelID)} + coptions.Apply(&options, opts) if options.refreshInterval == 0 { @@ -355,6 +338,10 @@ func asPeer(ctx contextAPI.Client, endpoint *discclient.Peer) (fab.Peer, error) }, nil } +func getDefaultRetryOpts(ctx contextAPI.Client, channelID string) retry.Opts { + return ctx.EndpointConfig().ChannelConfig(channelID).Policies.Discovery.RetryOpts +} + type peerEndpoint struct { fab.Peer blockHeight uint64 diff --git a/pkg/fab/default_channel_test.go b/pkg/fab/default_channel_test.go index 02a556c31c..f82c5ec13f 100644 --- a/pkg/fab/default_channel_test.go +++ b/pkg/fab/default_channel_test.go @@ -35,6 +35,10 @@ func TestDefaultChannelWithDefaultChannelConfiguredAndNoMatchers(t *testing.T) { assert.Equal(t, 3, chConfig.Policies.QueryChannelConfig.MaxTargets) assert.Equal(t, 1, chConfig.Policies.Discovery.MinResponses) assert.Equal(t, 3, chConfig.Policies.Discovery.MaxTargets) + assert.Equal(t, 2, chConfig.Policies.Discovery.RetryOpts.Attempts) + assert.Equal(t, 2*time.Second, chConfig.Policies.Discovery.RetryOpts.InitialBackoff) + assert.Equal(t, 7*time.Second, chConfig.Policies.Discovery.RetryOpts.MaxBackoff) + assert.Equal(t, 2, len(chConfig.Policies.Discovery.RetryOpts.RetryableCodes)) eventPolicies := chConfig.Policies.EventService assert.Equalf(t, fab.BalancedStrategy, eventPolicies.ResolverStrategy, "Unexpected value for ResolverStrategy") diff --git a/pkg/fab/endpointconfig.go b/pkg/fab/endpointconfig.go index c08b77b586..1cccc33161 100644 --- a/pkg/fab/endpointconfig.go +++ b/pkg/fab/endpointconfig.go @@ -17,6 +17,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/multi" "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry" + "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status" "github.com/hyperledger/fabric-sdk-go/pkg/common/logging" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core" "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab" @@ -28,6 +29,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + grpcCodes "google.golang.org/grpc/codes" ) var logger = logging.NewLogger("fabsdk/fab") @@ -76,6 +78,23 @@ const ( ) var ( + defaultDiscoveryRetryableCodes = map[status.Group][]status.Code{ + status.GRPCTransportStatus: { + status.Code(grpcCodes.Unavailable), + }, + status.DiscoveryServerStatus: { + status.QueryEndorsers, + }, + } + + defaultDiscoveryRetryOpts = retry.Opts{ + Attempts: 6, + InitialBackoff: 500 * time.Millisecond, + MaxBackoff: 5 * time.Second, + BackoffFactor: 1.75, + RetryableCodes: defaultDiscoveryRetryableCodes, + } + defaultChannelPolicies = &ChannelPolicies{ QueryChannelConfig: QueryChannelConfigPolicy{ MaxTargets: defaultMaxTargets, @@ -85,7 +104,7 @@ var ( Discovery: DiscoveryPolicy{ MaxTargets: defaultMaxTargets, MinResponses: defaultMinResponses, - RetryOpts: retry.Opts{}, + RetryOpts: defaultDiscoveryRetryOpts, }, Selection: SelectionPolicy{ SortingStrategy: BlockHeightPriority, @@ -997,6 +1016,10 @@ func (c *EndpointConfig) loadDefaultDiscoveryPolicy(policy *fab.DiscoveryPolicy) if policy.MinResponses == 0 { policy.MinResponses = defaultMinResponses } + + if len(policy.RetryOpts.RetryableCodes) == 0 { + policy.RetryOpts.RetryableCodes = defaultDiscoveryRetryableCodes + } } func (c *EndpointConfig) loadDefaultSelectionPolicy(policy *fab.SelectionPolicy) {