From cedd07bbc80fd6f1e1ed1fc4238e7c5320fb45d1 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 3 May 2023 15:58:21 +0300 Subject: [PATCH] [#304] morph: Iterate endpoints when create ws client in constructor Signed-off-by: Anton Nikiforov --- CHANGELOG.md | 1 + internal/logs/logs.go | 2 ++ pkg/morph/client/constructor.go | 24 +++++++++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60a5d7d92..281386256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Changelog for FrostFS Node - Read config files from dir even if config file not provided via `--config` for node (#238) - Notary requests parsing according to `neo-go`'s updates (#268) - Tree service panic in its internal client cache (#322) +- Iterate over endpoints when create ws client in morph's constructor (#304) ### Removed ### Updated diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ab7b8f63c..9b6e03499 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -413,6 +413,8 @@ const ( FrostFSIRInternalError = "internal error" // Info in ../node/cmd/frostfs-ir/main.go FrostFSIRCouldNotShutdownHTTPServer = "could not shutdown HTTP server" // Debug in ../node/cmd/frostfs-ir/main.go FrostFSIRApplicationStopped = "application stopped" // Info in ../node/cmd/frostfs-ir/main.go + FrostFSIRCouldntCreateRPCClientForEndpoint = "could not create RPC client for endpoint" // Debug in ../node/pkg/morph/client/constructor.go + FrostFSIRCreatedRPCClientForEndpoint = "created RPC client for endpoint" // Info in ../node/pkg/morph/client/constructor.go FrostFSNodeCouldNotReadCertificateFromFile = "could not read certificate from file" // Error in ../node/cmd/frostfs-node/grpc.go FrostFSNodeCantListenGRPCEndpoint = "can't listen gRPC endpoint" // Error in ../node/cmd/frostfs-node/grpc.go FrostFSNodeStopListeningGRPCEndpoint = "stop listening gRPC endpoint" // Info in ../node/cmd/frostfs-node/grpc.go diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index c4ec70171..4232b349d 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" lru "github.com/hashicorp/golang-lru/v2" "github.com/nspcc-dev/neo-go/pkg/core/block" @@ -52,6 +53,10 @@ const ( defaultWaitInterval = 500 * time.Millisecond ) +var ( + ErrNoHealthyEndpoint = errors.New("no healthy endpoint") +) + func defaultConfig() *cfg { return &cfg{ dialTimeout: defaultDialTimeout, @@ -80,6 +85,8 @@ func defaultConfig() *cfg { // If desired option satisfies the default value, it can be omitted. // If multiple options of the same config value are supplied, // the option with the highest index in the arguments will be used. +// If the list of endpoints provided - uses first alive. +// If there are no healthy endpoint - returns ErrNoHealthyEndpoint. func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, error) { if key == nil { panic("empty private key") @@ -137,9 +144,20 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er return nil, fmt.Errorf("could not create RPC actor: %w", err) } } else { - cli.client, act, err = cli.newCli(ctx, cli.endpoints.list[0].Address) - if err != nil { - return nil, fmt.Errorf("could not create RPC client: %w", err) + var endpoint Endpoint + for cli.endpoints.curr, endpoint = range cli.endpoints.list { + cli.client, act, err = cli.newCli(ctx, endpoint.Address) + if err != nil { + cli.logger.Warn(logs.FrostFSIRCouldntCreateRPCClientForEndpoint, + zap.Error(err), zap.String("endpoint", endpoint.Address)) + } else { + cli.logger.Info(logs.FrostFSIRCreatedRPCClientForEndpoint, + zap.String("endpoint", endpoint.Address)) + break + } + } + if cli.client == nil { + return nil, ErrNoHealthyEndpoint } } cli.setActor(act)