From f18b2ce39fc7257360f81cb2627e69767c9a506b Mon Sep 17 00:00:00 2001 From: "maksim.konovalov" Date: Thu, 9 Jan 2025 13:03:50 +0300 Subject: [PATCH] Ignore instance uuid field Instance uuid is no longer required as it does not cause problems with both tarantool 2 and tarantool 3 --- CHANGELOG.md | 6 ++++++ go.mod | 2 -- tarantool_test.go | 42 ++++++++++++++++++++++++++++++++++++++ tests/tnt/cfgmaker.go | 2 ++ tests/tnt/topology_test.go | 2 +- topology.go | 27 ++++++++++++++++++------ topology_test.go | 4 ++-- vshard.go | 25 ++++++++++++++++++----- vshard_shadow_test.go | 10 ++++----- 9 files changed, 99 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f93f6d6..03de5e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +CHANGES: +* Instance UUID no more required, use instance name instead. +* Removed toolchain go1.23.3. + ## v1.3.2 CHANGES: diff --git a/go.mod b/go.mod index 1d02c3f..61d166d 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/tarantool/go-vshard-router go 1.22 -toolchain go1.23.3 - require ( github.com/google/uuid v1.6.0 github.com/snksoft/crc v1.1.0 diff --git a/tarantool_test.go b/tarantool_test.go index 7105a26..2e53dbe 100644 --- a/tarantool_test.go +++ b/tarantool_test.go @@ -64,6 +64,35 @@ var topology = map[vshardrouter.ReplicasetInfo][]vshardrouter.InstanceInfo{ }, } +var noUUIDTopology = map[vshardrouter.ReplicasetInfo][]vshardrouter.InstanceInfo{ + { + Name: "storage_1", + Weight: 1, + }: { + { + Name: "storage_1_a", + Addr: "127.0.0.1:3301", + }, + { + Name: "storage_1_b", + Addr: "127.0.0.1:3302", + }, + }, + { + Name: "storage_2", + Weight: 1, + }: { + { + Name: "storage_2_a", + Addr: "127.0.0.1:3303", + }, + { + Name: "storage_2_b", + Addr: "127.0.0.1:3304", + }, + }, +} + func runTestMain(m *testing.M) int { dialers := make([]tarantool.NetDialer, instancesCount) opts := make([]test_helpers.StartOpts, instancesCount) @@ -157,3 +186,16 @@ func TestRouter_RouterCallImpl_Decoding(t *testing.T) { require.NoError(t, err) } + +// for tarantool 3.0 uuid is not required +func TestNewRouter_IgnoreUUID(t *testing.T) { + ctx := context.Background() + + _, err := vshardrouter.NewRouter(ctx, vshardrouter.Config{ + TotalBucketCount: 100, + TopologyProvider: static.NewProvider(noUUIDTopology), + User: "guest", + }) + + require.NoError(t, err) +} diff --git a/tests/tnt/cfgmaker.go b/tests/tnt/cfgmaker.go index 405e558..6a7ba01 100644 --- a/tests/tnt/cfgmaker.go +++ b/tests/tnt/cfgmaker.go @@ -61,9 +61,11 @@ func (c cfgmaker) clusterCfg() map[vshardrouter.ReplicasetInfo][]vshardrouter.In Name: fmt.Sprintf("replicaset_%d", rsID), UUID: c.replicasetUUID(rsID), }] = []vshardrouter.InstanceInfo{{ + Name: "inst_1", Addr: c.masterAddr(rsID), UUID: c.masterUUID(rsID), }, { + Name: "inst_2", Addr: c.followerAddr(rsID), UUID: c.followerUUID(rsID), }} diff --git a/tests/tnt/topology_test.go b/tests/tnt/topology_test.go index e3df5d3..dbcd8d3 100644 --- a/tests/tnt/topology_test.go +++ b/tests/tnt/topology_test.go @@ -49,7 +49,7 @@ func TestTopology(t *testing.T) { require.Nil(t, err, "AddReplicasets finished successfully") // remove some random instance - err = router.RemoveInstance(ctx, rsInfo.UUID, insInfo.UUID) + err = router.RemoveInstance(ctx, rsInfo.UUID, insInfo.Name) require.Nil(t, err, "RemoveInstance finished successfully") // add it again diff --git a/topology.go b/topology.go index 5ebc097..9e8870c 100644 --- a/topology.go +++ b/topology.go @@ -21,7 +21,7 @@ var ( type TopologyController interface { AddInstance(ctx context.Context, rsID uuid.UUID, info InstanceInfo) error RemoveReplicaset(ctx context.Context, rsID uuid.UUID) []error - RemoveInstance(ctx context.Context, rsID, instanceID uuid.UUID) error + RemoveInstance(ctx context.Context, rsID uuid.UUID, instanceName string) error AddReplicaset(ctx context.Context, rsInfo ReplicasetInfo, instances []InstanceInfo) error AddReplicasets(ctx context.Context, replicasets map[ReplicasetInfo][]InstanceInfo) error } @@ -53,7 +53,7 @@ func (r *Router) AddInstance(ctx context.Context, rsID uuid.UUID, info InstanceI } instance := pool.Instance{ - Name: info.UUID.String(), + Name: info.Name, Dialer: tarantool.NetDialer{ Address: info.Addr, User: r.cfg.User, @@ -72,8 +72,8 @@ func (r *Router) AddInstance(ctx context.Context, rsID uuid.UUID, info InstanceI return rs.conn.Add(ctx, instance) } -func (r *Router) RemoveInstance(ctx context.Context, rsID, instanceID uuid.UUID) error { - r.log().Debugf(ctx, "Trying to remove instance %s from router topology in rs %s", instanceID, rsID) +func (r *Router) RemoveInstance(ctx context.Context, rsID uuid.UUID, instanceName string) error { + r.log().Debugf(ctx, "Trying to remove instance %s from router topology in rs %s", instanceName, rsID) idToReplicasetRef := r.getIDToReplicaset() @@ -82,7 +82,7 @@ func (r *Router) RemoveInstance(ctx context.Context, rsID, instanceID uuid.UUID) return ErrReplicasetNotExists } - return rs.conn.Remove(instanceID.String()) + return rs.conn.Remove(instanceName) } func (r *Router) AddReplicaset(ctx context.Context, rsInfo ReplicasetInfo, instances []InstanceInfo) error { @@ -90,6 +90,21 @@ func (r *Router) AddReplicaset(ctx context.Context, rsInfo ReplicasetInfo, insta idToReplicasetOld := r.getIDToReplicaset() + // tarantool 3+ configuration does not require uuid + if rsInfo.UUID == uuid.Nil { + // check that such replicaset does not exist + for _, rs := range idToReplicasetOld { + if rs.info.Name == rsInfo.Name { + return ErrReplicasetExists + } + } + + // we just mock this uuid value + rsInfo.UUID = uuid.New() + + r.log().Warnf(ctx, "replicaset %s is assigned uuid %s; this is a temporary need to migrate from uuid to names", rsInfo.Name, rsInfo.UUID) + } + if _, ok := idToReplicasetOld[rsInfo.UUID]; ok { return ErrReplicasetExists } @@ -101,7 +116,7 @@ func (r *Router) AddReplicaset(ctx context.Context, rsInfo ReplicasetInfo, insta rsInstances := make([]pool.Instance, 0, len(instances)) for _, instance := range instances { rsInstances = append(rsInstances, pool.Instance{ - Name: instance.UUID.String(), + Name: instance.Name, Dialer: tarantool.NetDialer{ Address: instance.Addr, User: r.cfg.User, diff --git a/topology_test.go b/topology_test.go index 70f8ff8..f3f17ac 100644 --- a/topology_test.go +++ b/topology_test.go @@ -29,7 +29,7 @@ func TestController_AddInstance(t *testing.T) { err := router.Topology().AddInstance(ctx, uuid.New(), InstanceInfo{ Addr: "127.0.0.1:8060", - UUID: uuid.New(), + Name: "instance_001", }) require.True(t, errors.Is(err, ErrReplicasetNotExists)) }) @@ -58,7 +58,7 @@ func TestController_RemoveInstance(t *testing.T) { }, } - err := router.Topology().RemoveInstance(ctx, uuid.New(), uuid.New()) + err := router.Topology().RemoveInstance(ctx, uuid.New(), "") require.True(t, errors.Is(err, ErrReplicasetNotExists)) }) } diff --git a/vshard.go b/vshard.go index 98e9773..d90e581 100644 --- a/vshard.go +++ b/vshard.go @@ -167,22 +167,37 @@ func (bsi *BucketStatInfo) DecodeMsgpack(d *msgpack.Decoder) error { return nil } +// InstanceInfo represents the information about an instance. +// This struct holds the necessary details such as the name, address, and UUID of the instance. type InstanceInfo struct { - // Name is human-readable id for instance - // Starting with tarantool 3.0, the definition is made into a human-readable name, - // so far it is not used directly inside the library + // Name is a required field for the instance. + // Starting with Tarantool 3.0, this definition is made into a human-readable name, + // and it is now mandatory for use in the library. + // The Name should be a unique identifier for the instance. Name string + + // Addr specifies the address of the instance. + // This can be an IP address or a domain name, depending on how the instance is accessed. + // It is necessary for connecting to the instance or identifying its location. Addr string + + // UUID is an optional field that provides a globally unique identifier (UUID) for the instance. + // While this information is not mandatory, it can be useful for internal management or tracking purposes. + // The UUID ensures that each instance can be identified uniquely, but it is not required for basic operations. UUID uuid.UUID } func (ii InstanceInfo) String() string { + if ii.UUID == uuid.Nil { + return fmt.Sprintf("{name: %s, addr: %s}", ii.Name, ii.Addr) + } + return fmt.Sprintf("{name: %s, uuid: %s, addr: %s}", ii.Name, ii.UUID, ii.Addr) } func (ii InstanceInfo) Validate() error { - if ii.UUID == uuid.Nil { - return fmt.Errorf("%w: empty uuid", ErrInvalidInstanceInfo) + if ii.Name == "" { + return fmt.Errorf("%w: empty name", ErrInvalidInstanceInfo) } if ii.Addr == "" { diff --git a/vshard_shadow_test.go b/vshard_shadow_test.go index be83dd3..63e06a3 100644 --- a/vshard_shadow_test.go +++ b/vshard_shadow_test.go @@ -96,9 +96,9 @@ func TestInstanceInfo_Validate(t *testing.T) { Valid: false, }, { - Name: "no uuid", - II: vshardrouter.InstanceInfo{Addr: "first.internal:1212"}, - Valid: false, + Name: "no uuid - ok", + II: vshardrouter.InstanceInfo{Addr: "first.internal:1212", Name: "instance_123"}, + Valid: true, }, { Name: "no addr", @@ -106,9 +106,9 @@ func TestInstanceInfo_Validate(t *testing.T) { Valid: false, }, { - Name: "ok", + Name: "no instance name", II: vshardrouter.InstanceInfo{UUID: uuid.New(), Addr: "first.internal:1212"}, - Valid: true, + Valid: false, }, }