From 02f2a98bccca618e488ac0952503ccaa9780e77f Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 9 Sep 2021 02:13:55 +0300 Subject: [PATCH] [#778] services/object: Return the composite error of PUT operation In previous implementation Object service's handler returned const error in case of failure (full or partial) of PUT operation. This did not even allow us to roughly guess what the reason is. Not as a complete solution, but to alleviate some cases where all nodes in a container return the same error, it is suggested to return the error of the last server that responded. Return latest server error from placement loop of `iteratePlacement` method of `distributedTarget` type. Signed-off-by: Leonard Lyubich --- pkg/services/object/put/distributed.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 10ec88ec4..20abae0c1 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "sync" + "sync/atomic" "github.com/nspcc-dev/neofs-node/pkg/core/object" svcutil "github.com/nspcc-dev/neofs-node/pkg/services/object/util" @@ -93,6 +94,8 @@ func (t *distributedTarget) iteratePlacement(f func(placement.Node) error) (*tra return nil, fmt.Errorf("(%T) could not create object placement traverser: %w", t, err) } + var resErr atomic.Value + loop: for { addrs := traverser.Next() @@ -110,6 +113,7 @@ loop: defer wg.Done() if err := f(addr); err != nil { + resErr.Store(err) svcutil.LogServiceError(t.log, "PUT", addr.Addresses(), err) return } @@ -128,6 +132,10 @@ loop: } if !traverser.Success() { + if err, ok := resErr.Load().(error); ok { + return nil, err + } + return nil, errIncompletePut }