diff --git a/api/handler/handlers_test.go b/api/handler/handlers_test.go index 4fb911bf..f1dbd9a5 100644 --- a/api/handler/handlers_test.go +++ b/api/handler/handlers_test.go @@ -121,7 +121,7 @@ func prepareHandlerContext(t *testing.T) *handlerContext { func NewTreeServiceMock(t *testing.T) *tree.Tree { memCli, err := tree.NewTreeServiceClientMemory() require.NoError(t, err) - return tree.NewTree(memCli) + return tree.NewTree(memCli, zap.NewExample()) } func createTestBucket(hc *handlerContext, bktName string) *data.BucketInfo { diff --git a/cmd/s3-gw/app.go b/cmd/s3-gw/app.go index f4faff2c..f1ad6a91 100644 --- a/cmd/s3-gw/app.go +++ b/cmd/s3-gw/app.go @@ -119,7 +119,7 @@ func (a *App) initLayer(ctx context.Context) { if err != nil { a.log.Fatal("failed to create tree service", zap.Error(err)) } - treeService := tree.NewTree(treeGRPCClient) + treeService := tree.NewTree(treeGRPCClient, a.log) a.log.Info("init tree service", zap.Strings("endpoints", treeGRPCClient.Endpoints())) // prepare random key for anonymous requests diff --git a/go.mod b/go.mod index 60cd8d7d..cedb8268 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect git.frostfs.info/TrueCloudLab/tzhash v1.8.0 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect + github.com/benbjohnson/clock v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect diff --git a/pkg/service/tree/tree.go b/pkg/service/tree/tree.go index 43c59602..97fb6d93 100644 --- a/pkg/service/tree/tree.go +++ b/pkg/service/tree/tree.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "sort" "strconv" "strings" "time" @@ -12,11 +13,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "go.uber.org/zap" ) type ( Tree struct { service ServiceClient + log *zap.Logger } // ServiceClient is a client to interact with tree service. @@ -104,8 +107,11 @@ const ( ) // NewTree creates instance of Tree using provided address and create grpc connection. -func NewTree(service ServiceClient) *Tree { - return &Tree{service: service} +func NewTree(service ServiceClient, log *zap.Logger) *Tree { + return &Tree{ + service: service, + log: log, + } } type Meta interface { @@ -811,14 +817,19 @@ func (c *Tree) getUnversioned(ctx context.Context, bktInfo *data.BucketInfo, tre return nil, err } - if len(nodes) > 1 { - return nil, fmt.Errorf("found more than one unversioned node") - } - - if len(nodes) != 1 { + if len(nodes) == 0 { return nil, layer.ErrNodeNotFound } + if len(nodes) > 1 { + c.log.Debug("found more than one unversioned node", zap.Stringer("cid", bktInfo.CID), + zap.String("treeID", treeID), zap.String("filepath", filepath)) + } + + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].Timestamp > nodes[j].Timestamp + }) + return nodes[0], nil } diff --git a/pkg/service/tree/tree_test.go b/pkg/service/tree/tree_test.go index 271027f9..2e392309 100644 --- a/pkg/service/tree/tree_test.go +++ b/pkg/service/tree/tree_test.go @@ -8,6 +8,7 @@ import ( cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" ) func TestLockConfigurationEncoding(t *testing.T) { @@ -102,7 +103,7 @@ func TestTreeServiceSettings(t *testing.T) { memCli, err := NewTreeServiceClientMemory() require.NoError(t, err) - treeService := NewTree(memCli) + treeService := NewTree(memCli, zaptest.NewLogger(t)) bktInfo := &data.BucketInfo{ CID: cidtest.ID(), @@ -134,7 +135,7 @@ func TestTreeServiceAddVersion(t *testing.T) { memCli, err := NewTreeServiceClientMemory() require.NoError(t, err) - treeService := NewTree(memCli) + treeService := NewTree(memCli, zaptest.NewLogger(t)) bktInfo := &data.BucketInfo{ CID: cidtest.ID(),