diff --git a/go/vt/key/key.go b/go/vt/key/key.go index 82852daa16e..09d4bad2975 100644 --- a/go/vt/key/key.go +++ b/go/vt/key/key.go @@ -438,7 +438,7 @@ func GenerateShardRanges(shards int) ([]string, error) { realEnd := float64(0) shardRanges := make([]string, 0, shards) - for i := 1; i <= shards; i++ { + for i := 1; i < shards; i++ { realEnd = float64(i) * size end = int(realEnd) @@ -446,5 +446,7 @@ func GenerateShardRanges(shards int) ([]string, error) { start = end } + shardRanges = append(shardRanges, rangeFormatter(start, maxShards)) + return shardRanges, nil } diff --git a/go/vt/key/key_test.go b/go/vt/key/key_test.go index 84d4365ff0e..00ba4477e2b 100644 --- a/go/vt/key/key_test.go +++ b/go/vt/key/key_test.go @@ -18,6 +18,7 @@ package key import ( "encoding/hex" + "fmt" "strings" "testing" @@ -1523,6 +1524,24 @@ func TestGenerateShardRanges(t *testing.T) { []string{"-24", "24-49", "49-6d", "6d-92", "92-b6", "b6-db", "db-"}, false, }, + { + "works for 49 shards", + args{49}, + []string{"-05", "05-0a", "0a-0f", "0f-14", "14-1a", "1a-1f", "1f-24", "24-29", "29-2f", "2f-34", "34-39", "39-3e", "3e-43", "43-49", "49-4e", "4e-53", "53-58", "58-5e", "5e-63", "63-68", "68-6d", "6d-72", "72-78", "78-7d", "7d-82", "82-87", "87-8d", "8d-92", "92-97", "97-9c", "9c-a1", "a1-a7", "a7-ac", "ac-b1", "b1-b6", "b6-bc", "bc-c1", "c1-c6", "c6-cb", "cb-d0", "d0-d6", "d6-db", "db-e0", "e0-e5", "e5-eb", "eb-f0", "f0-f5", "f5-fa", "fa-"}, + false, + }, + { + "works for 103 shards", + args{103}, + []string{"-02", "02-04", "04-07", "07-09", "09-0c", "0c-0e", "0e-11", "11-13", "13-16", "16-18", "18-1b", "1b-1d", "1d-20", "20-22", "22-25", "25-27", "27-2a", "2a-2c", "2c-2f", "2f-31", "31-34", "34-36", "36-39", "39-3b", "3b-3e", "3e-40", "40-43", "43-45", "45-48", "48-4a", "4a-4d", "4d-4f", "4f-52", "52-54", "54-56", "56-59", "59-5b", "5b-5e", "5e-60", "60-63", "63-65", "65-68", "68-6a", "6a-6d", "6d-6f", "6f-72", "72-74", "74-77", "77-79", "79-7c", "7c-7e", "7e-81", "81-83", "83-86", "86-88", "88-8b", "8b-8d", "8d-90", "90-92", "92-95", "95-97", "97-9a", "9a-9c", "9c-9f", "9f-a1", "a1-a4", "a4-a6", "a6-a9", "a9-ab", "ab-ad", "ad-b0", "b0-b2", "b2-b5", "b5-b7", "b7-ba", "ba-bc", "bc-bf", "bf-c1", "c1-c4", "c4-c6", "c6-c9", "c9-cb", "cb-ce", "ce-d0", "d0-d3", "d3-d5", "d5-d8", "d8-da", "da-dd", "dd-df", "df-e2", "e2-e4", "e4-e7", "e7-e9", "e9-ec", "ec-ee", "ee-f1", "f1-f3", "f3-f6", "f6-f8", "f8-fb", "fb-fd", "fd-"}, + false, + }, + { + "works for 107 shards", + args{107}, + []string{"-02", "02-04", "04-07", "07-09", "09-0b", "0b-0e", "0e-10", "10-13", "13-15", "15-17", "17-1a", "1a-1c", "1c-1f", "1f-21", "21-23", "23-26", "26-28", "28-2b", "2b-2d", "2d-2f", "2f-32", "32-34", "34-37", "37-39", "39-3b", "3b-3e", "3e-40", "40-42", "42-45", "45-47", "47-4a", "4a-4c", "4c-4e", "4e-51", "51-53", "53-56", "56-58", "58-5a", "5a-5d", "5d-5f", "5f-62", "62-64", "64-66", "66-69", "69-6b", "6b-6e", "6e-70", "70-72", "72-75", "75-77", "77-7a", "7a-7c", "7c-7e", "7e-81", "81-83", "83-85", "85-88", "88-8a", "8a-8d", "8d-8f", "8f-91", "91-94", "94-96", "96-99", "99-9b", "9b-9d", "9d-a0", "a0-a2", "a2-a5", "a5-a7", "a7-a9", "a9-ac", "ac-ae", "ae-b1", "b1-b3", "b3-b5", "b5-b8", "b8-ba", "ba-bd", "bd-bf", "bf-c1", "c1-c4", "c4-c6", "c6-c8", "c8-cb", "cb-cd", "cd-d0", "d0-d2", "d2-d4", "d4-d7", "d7-d9", "d9-dc", "dc-de", "de-e0", "e0-e3", "e3-e5", "e5-e8", "e8-ea", "ea-ec", "ec-ef", "ef-f1", "f1-f4", "f4-f6", "f6-f8", "f8-fb", "fb-fd", "fd-"}, + false, + }, { "works for large number of shards", args{256}, @@ -1545,6 +1564,29 @@ func TestGenerateShardRanges(t *testing.T) { } } +func TestGenerateShardRangesForManyShards(t *testing.T) { + for i := 1; i <= 1024; i++ { + t.Run(fmt.Sprintf("shards=%d", i), func(t *testing.T) { + ranges, err := GenerateShardRanges(i) + + require.NoError(t, err) + require.Len(t, ranges, i) + + // verify that the shards are contiguous and non-overlapping + for j := 1; j < len(ranges); j++ { + prevEnd := ranges[j-1][strings.Index(ranges[j-1], "-")+1:] + currStart := ranges[j][:strings.Index(ranges[j], "-")] + + require.Equal(t, prevEnd, currStart, "Shards %d and %d are not contiguous: %s != %s", j-1, j, prevEnd, currStart) + } + + // verify that the shards cover the full keyspace + require.True(t, strings.HasPrefix(ranges[0], "-"), "First shard does not start with a hyphen: %s", ranges[0]) + require.True(t, strings.HasSuffix(ranges[len(ranges)-1], "-"), "Last shard does not end with a hyphen: %s", ranges[len(ranges)-1]) + }) + } +} + func TestShardCalculatorForShardsGreaterThan512(t *testing.T) { got, err := GenerateShardRanges(512) assert.NoError(t, err)