Skip to content

Commit

Permalink
Merge pull request #25 from buraksezer/fix/issue-19
Browse files Browse the repository at this point in the history
fix: AverageLoad() function panics with "divide by zero" when no members are in the hash ring
  • Loading branch information
buraksezer committed Nov 9, 2022
2 parents 77eb2fa + dc3cf9d commit ae9f2ab
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 12 deletions.
15 changes: 13 additions & 2 deletions consistent.go
Expand Up @@ -136,7 +136,7 @@ func New(members []Member, config Config) *Consistent {
return c
}

// GetMembers returns a thread-safe copy of members.
// GetMembers returns a thread-safe copy of members. If there are no members, it returns an empty slice of Member.
func (c *Consistent) GetMembers() []Member {
c.mu.RLock()
defer c.mu.RUnlock()
Expand All @@ -151,12 +151,23 @@ func (c *Consistent) GetMembers() []Member {

// AverageLoad exposes the current average load.
func (c *Consistent) AverageLoad() float64 {
c.mu.RLock()
defer c.mu.RUnlock()

return c.averageLoad()
}

func (c *Consistent) averageLoad() float64 {
if len(c.members) == 0 {
return 0
}

avgLoad := float64(c.partitionCount/uint64(len(c.members))) * c.config.Load
return math.Ceil(avgLoad)
}

func (c *Consistent) distributeWithLoad(partID, idx int, partitions map[int]*Member, loads map[string]float64) {
avgLoad := c.AverageLoad()
avgLoad := c.averageLoad()
var count int
for {
count++
Expand Down
30 changes: 20 additions & 10 deletions consistent_test.go
Expand Up @@ -95,22 +95,32 @@ func TestConsistentRemove(t *testing.T) {
}

func TestConsistentLoad(t *testing.T) {
members := []Member{}
var members []Member
for i := 0; i < 8; i++ {
member := testMember(fmt.Sprintf("node%d.olric", i))
members = append(members, member)
}
cfg := newConfig()
c := New(members, cfg)
if len(c.GetMembers()) != len(members) {
t.Fatalf("inserted member count is different")
}
maxLoad := c.AverageLoad()
for member, load := range c.LoadDistribution() {
if load > maxLoad {
t.Fatalf("%s exceeds max load. Its load: %f, max load: %f", member, load, maxLoad)

t.Run("Average load should be greater than the member's load", func(t *testing.T) {
c := New(members, cfg)
if len(c.GetMembers()) != len(members) {
t.Fatalf("inserted member count is different")
}
}
maxLoad := c.AverageLoad()
for member, load := range c.LoadDistribution() {
if load > maxLoad {
t.Fatalf("%s exceeds max load. Its load: %f, max load: %f", member, load, maxLoad)
}
}
})

t.Run("Average load should equal to zero if there are no members", func(t *testing.T) {
c := New(nil, cfg)
if c.AverageLoad() != 0 {
t.Fatalf("AverageLoad should equal to zero")
}
})
}

func TestConsistentLocateKey(t *testing.T) {
Expand Down

0 comments on commit ae9f2ab

Please sign in to comment.