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) {