Skip to content

Commit 8639de2

Browse files
Multi-tenant migrations: add topo locking while updating keyspace routing rules (#15807)
Signed-off-by: Rohit Nayak <rohit@planetscale.com> Signed-off-by: Matt Lord <mattalord@gmail.com> Co-authored-by: Matt Lord <mattalord@gmail.com>
1 parent 715f61e commit 8639de2

File tree

21 files changed

+2983
-2134
lines changed

21 files changed

+2983
-2134
lines changed

go/cmd/vtctldclient/command/keyspace_routing_rules.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ var applyKeyspaceRoutingRulesOptions = struct {
7070
func commandApplyKeyspaceRoutingRules(cmd *cobra.Command, args []string) error {
7171
opts := applyKeyspaceRoutingRulesOptions
7272
cli.FinishedParsing(cmd)
73-
7473
var rulesBytes []byte
7574
if opts.RulesFilePath != "" {
7675
data, err := os.ReadFile(opts.RulesFilePath)
@@ -86,13 +85,14 @@ func commandApplyKeyspaceRoutingRules(cmd *cobra.Command, args []string) error {
8685
if err := json2.Unmarshal(rulesBytes, &krr); err != nil {
8786
return err
8887
}
89-
// Round-trip so that when we display the result it's readable.
90-
data, err := cli.MarshalJSON(krr)
91-
if err != nil {
92-
return err
93-
}
9488

9589
if opts.DryRun {
90+
// Round-trip so that when we display the result it's readable.
91+
data, err := cli.MarshalJSON(krr)
92+
if err != nil {
93+
return err
94+
}
95+
9696
fmt.Printf("[DRY RUN] Would have saved new KeyspaceRoutingRules object:\n%s\n", data)
9797

9898
if opts.SkipRebuild {
@@ -105,11 +105,10 @@ func commandApplyKeyspaceRoutingRules(cmd *cobra.Command, args []string) error {
105105
fmt.Printf(" in the following cells: %s.\n", strings.Join(applyKeyspaceRoutingRulesOptions.Cells, ", "))
106106
}
107107
}
108-
109108
return nil
110109
}
111110

112-
_, err = client.ApplyKeyspaceRoutingRules(commandCtx, &vtctldatapb.ApplyKeyspaceRoutingRulesRequest{
111+
resp, err := client.ApplyKeyspaceRoutingRules(commandCtx, &vtctldatapb.ApplyKeyspaceRoutingRulesRequest{
113112
KeyspaceRoutingRules: krr,
114113
SkipRebuild: opts.SkipRebuild,
115114
RebuildCells: opts.Cells,
@@ -118,12 +117,11 @@ func commandApplyKeyspaceRoutingRules(cmd *cobra.Command, args []string) error {
118117
return err
119118
}
120119

121-
fmt.Printf("New KeyspaceRoutingRules object:\n%s\nIf this is not what you expected, check the input data (as JSON parsing will skip unexpected fields).\n", data)
122-
123-
if opts.SkipRebuild {
124-
fmt.Println("Skipping rebuild of VSchema graph as requested, you will need to run RebuildVSchemaGraph for the changes to take effect.")
120+
respJSON, err := cli.MarshalJSON(resp)
121+
if err != nil {
122+
return err
125123
}
126-
124+
fmt.Printf("%s\n", respJSON)
127125
return nil
128126
}
129127

go/test/endtoend/vreplication/multi_tenant_test.go

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ import (
3737
"testing"
3838
"time"
3939

40-
"google.golang.org/protobuf/encoding/protojson"
41-
4240
"github.com/stretchr/testify/require"
41+
"google.golang.org/protobuf/encoding/protojson"
4342

4443
"vitess.io/vitess/go/vt/log"
44+
"vitess.io/vitess/go/vt/proto/vtctldata"
45+
4546
binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
4647
vschemapb "vitess.io/vitess/go/vt/proto/vschema"
47-
"vitess.io/vitess/go/vt/proto/vtctldata"
4848
)
4949

5050
type tenantMigrationStatus int
@@ -71,6 +71,8 @@ var (
7171
chNotSetup, chNotCreated, chInProgress, chSwitched, chCompleted chan int64
7272
// counters to keep track of the number of tenants in each state
7373
numSetup, numInProgress, numSwitched, numCompleted atomic.Int64
74+
75+
emptyKeyspaceRoutingRules = &vschemapb.KeyspaceRoutingRules{}
7476
)
7577

7678
// multiTenantMigration manages the migration of multiple tenants to a single target keyspace.
@@ -193,6 +195,7 @@ func TestMultiTenantSimple(t *testing.T) {
193195
}
194196

195197
require.Zero(t, len(getKeyspaceRoutingRules(t, vc).Rules))
198+
196199
mt.Create()
197200
confirmKeyspacesRoutedTo(t, sourceKeyspace, "s1", "t1", nil)
198201
validateKeyspaceRoutingRules(t, vc, initialRules)
@@ -223,6 +226,41 @@ func TestMultiTenantSimple(t *testing.T) {
223226
log.Infof("Migration completed, total rows in target: %d", actualRowsInserted)
224227
require.Equal(t, lastIndex, int64(actualRowsInserted))
225228

229+
t.Run("Test ApplyKeyspaceRoutingRules", func(t *testing.T) {
230+
// First set of rules
231+
applyKeyspaceRoutingRules(t, initialRules)
232+
233+
updatedRules := &vschemapb.KeyspaceRoutingRules{
234+
Rules: []*vschemapb.KeyspaceRoutingRule{
235+
{FromKeyspace: "s1", ToKeyspace: "mt"},
236+
{FromKeyspace: "s1@rdonly", ToKeyspace: "mt"},
237+
{FromKeyspace: "s1@replica", ToKeyspace: "mt"},
238+
},
239+
}
240+
// Update the rules
241+
applyKeyspaceRoutingRules(t, updatedRules)
242+
// Update with the same rules
243+
applyKeyspaceRoutingRules(t, updatedRules)
244+
// Remove the rules
245+
applyKeyspaceRoutingRules(t, emptyKeyspaceRoutingRules)
246+
// Test setting empty rules again
247+
applyKeyspaceRoutingRules(t, emptyKeyspaceRoutingRules)
248+
})
249+
}
250+
251+
func applyKeyspaceRoutingRules(t *testing.T, newRules *vschemapb.KeyspaceRoutingRules) {
252+
var rulesJSON []byte
253+
var err error
254+
require.NotNil(t, newRules)
255+
rulesJSON, err = json.Marshal(newRules)
256+
require.NoError(t, err)
257+
output, err := vc.VtctldClient.ExecuteCommandWithOutput("ApplyKeyspaceRoutingRules", "--rules", string(rulesJSON))
258+
require.NoError(t, err)
259+
260+
response := &vtctldata.ApplyKeyspaceRoutingRulesResponse{}
261+
err = json.Unmarshal([]byte(output), response)
262+
require.NoError(t, err)
263+
require.ElementsMatch(t, newRules.Rules, response.GetKeyspaceRoutingRules().Rules)
226264
}
227265

228266
func confirmOnlyReadsSwitched(t *testing.T) {
@@ -251,10 +289,10 @@ func confirmOnlyWritesSwitched(t *testing.T) {
251289
validateKeyspaceRoutingRules(t, vc, rules)
252290
}
253291

254-
// TestMultiTenantSimpleSharded tests a single tenant migration to a sharded target. The aim is to test
292+
// TestMultiTenantSharded tests a single tenant migration to a sharded target. The aim is to test
255293
// the specification of the target shards in all the MoveTables subcommands, including creating only one stream
256294
// for a tenant on the shard to which this tenant id will be routed, using the specified Vindex.
257-
func TestMultiTenantSimpleSharded(t *testing.T) {
295+
func TestMultiTenantSharded(t *testing.T) {
258296
setSidecarDBName("_vt")
259297
// Don't create RDONLY tablets to reduce number of tablets created to reduce resource requirements for the test.
260298
origDefaultRdonly := defaultRdonly

0 commit comments

Comments
 (0)