Skip to content

Commit e108f70

Browse files
authored
Fix ring tokens sorting regression introduced in #3601 (#3815) (#3816)
Signed-off-by: Marco Pracucci <[email protected]>
1 parent 2b0d122 commit e108f70

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

pkg/ring/lifecycler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ func (i *Lifecycler) ClaimTokensFor(ctx context.Context, ingesterID string) erro
337337
// update timestamp to give gossiping client a chance register ring change.
338338
ing := ringDesc.Ingesters[i.ID]
339339
ing.Timestamp = time.Now().Unix()
340+
341+
// Tokens of the leaving ingester may have been generated by an older version of Cortex which
342+
// doesn't guarantee sorted tokens, so we enforce sorting here.
343+
sort.Sort(tokens)
344+
ing.Tokens = tokens
345+
340346
ringDesc.Ingesters[i.ID] = ing
341347
return ringDesc, true, nil
342348
}

pkg/ring/model.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,13 @@ func (d *Desc) getTokensInfo() map[uint32]instanceInfo {
406406
func (d *Desc) GetTokens() []uint32 {
407407
instances := make([][]uint32, 0, len(d.Ingesters))
408408
for _, instance := range d.Ingesters {
409-
instances = append(instances, instance.Tokens)
409+
// Tokens may not be sorted for an older version of Cortex which, so we enforce sorting here.
410+
tokens := instance.Tokens
411+
if !sort.IsSorted(Tokens(tokens)) {
412+
sort.Sort(Tokens(tokens))
413+
}
414+
415+
instances = append(instances, tokens)
410416
}
411417

412418
return MergeTokens(instances)
@@ -417,7 +423,13 @@ func (d *Desc) GetTokens() []uint32 {
417423
func (d *Desc) getTokensByZone() map[string][]uint32 {
418424
zones := map[string][][]uint32{}
419425
for _, instance := range d.Ingesters {
420-
zones[instance.Zone] = append(zones[instance.Zone], instance.Tokens)
426+
// Tokens may not be sorted for an older version of Cortex which, so we enforce sorting here.
427+
tokens := instance.Tokens
428+
if !sort.IsSorted(Tokens(tokens)) {
429+
sort.Sort(Tokens(tokens))
430+
}
431+
432+
zones[instance.Zone] = append(zones[instance.Zone], tokens)
421433
}
422434

423435
// Merge tokens per zone.

pkg/ring/tokens.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ func LoadTokensFromFile(tokenFilePath string) (Tokens, error) {
7878
}
7979
var t Tokens
8080
err = t.Unmarshal(b)
81+
82+
// Tokens may have been written to file by an older version of Cortex which
83+
// doesn't guarantee sorted tokens, so we enforce sorting here.
84+
if !sort.IsSorted(t) {
85+
sort.Sort(t)
86+
}
87+
8188
return t, err
8289
}
8390

@@ -92,7 +99,7 @@ func (t *Tokens) Unmarshal(b []byte) error {
9299
if err := json.Unmarshal(b, &tj); err != nil {
93100
return err
94101
}
95-
*t = Tokens(tj.Tokens)
102+
*t = tj.Tokens
96103
return nil
97104
}
98105

pkg/ring/tokens_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package ring
22

33
import (
4+
"io/ioutil"
45
"math/rand"
6+
"os"
7+
"path/filepath"
58
"testing"
69

710
"github.com/stretchr/testify/assert"
@@ -55,3 +58,20 @@ func TestTokens_Equals(t *testing.T) {
5558
assert.Equal(t, c.expected, c.second.Equals(c.first))
5659
}
5760
}
61+
62+
func TestLoadTokensFromFile_ShouldGuaranteeSortedTokens(t *testing.T) {
63+
tmpDir, err := ioutil.TempDir("", "test-tokens")
64+
require.NoError(t, err)
65+
t.Cleanup(func() {
66+
os.RemoveAll(tmpDir)
67+
})
68+
69+
// Store tokens to file.
70+
orig := Tokens{1, 5, 3}
71+
require.NoError(t, orig.StoreToFile(filepath.Join(tmpDir, "tokens")))
72+
73+
// Read back and ensure they're sorted.
74+
actual, err := LoadTokensFromFile(filepath.Join(tmpDir, "tokens"))
75+
require.NoError(t, err)
76+
assert.Equal(t, Tokens{1, 3, 5}, actual)
77+
}

0 commit comments

Comments
 (0)