From 87968070408915c975a64593a549be978cc4c9f9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Oct 2022 18:46:45 +0300 Subject: [PATCH] [#1936] network/cache: Handle dial errors After an SDK update `Dial` can return an error. Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 1 + pkg/network/cache/multi.go | 49 ++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e47683d31d..89e2a28f3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Changelog for NeoFS Node - Correctly handle setting ONLINE netmap status after maintenance (#1922) - Correctly reset shard errors in `ControlService.SetShardMode` RPC (#1931) - Setting node's network state to `MAINTENANCE` while network settings forbid it (#1916) +- Do not panic during API client creation (#1936) ### Removed ### Updated diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 2bb824796f..0ec48fb7fd 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -3,6 +3,7 @@ package cache import ( "context" "errors" + "fmt" "sync" rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" @@ -29,8 +30,7 @@ func newMultiClient(addr network.AddressGroup, opts ClientCacheOpts) *multiClien } } -// note: must be wrapped into mutex lock. -func (x *multiClient) createForAddress(addr network.Address) clientcore.Client { +func (x *multiClient) createForAddress(addr network.Address) (clientcore.Client, error) { var ( c client.Client prmInit client.PrmInit @@ -58,13 +58,10 @@ func (x *multiClient) createForAddress(addr network.Address) clientcore.Client { c.Init(prmInit) err := c.Dial(prmDial) if err != nil { - // client never returns an error - panic(err) + return nil, fmt.Errorf("can't init SDK client: %w", err) } - x.clients[addr.String()] = &c - - return &c + return &c, nil } // updateGroup replaces current multiClient addresses with a new group. @@ -106,9 +103,10 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie var err error - c := x.client(addr) - - err = f(c) + c, err := x.client(addr) + if err == nil { + err = f(c) + } success := err == nil || errors.Is(err, context.Canceled) @@ -231,25 +229,34 @@ func (x *multiClient) Close() error { } func (x *multiClient) RawForAddress(addr network.Address, f func(client *rawclient.Client) error) error { - return x.client(addr).ExecRaw(f) + c, err := x.client(addr) + if err != nil { + return err + } + return c.ExecRaw(f) } -func (x *multiClient) client(addr network.Address) clientcore.Client { +func (x *multiClient) client(addr network.Address) (clientcore.Client, error) { strAddr := addr.String() x.mtx.RLock() c, cached := x.clients[strAddr] x.mtx.RUnlock() - if !cached { - x.mtx.Lock() - - c, cached = x.clients[strAddr] - if !cached { - c = x.createForAddress(addr) - } - x.mtx.Unlock() + if cached { + return c, nil } - return c + x.mtx.Lock() + defer x.mtx.Unlock() + + c, cached = x.clients[strAddr] + if !cached { + c, err := x.createForAddress(addr) + if err != nil { + return nil, err + } + x.clients[strAddr] = c + } + return c, nil }