forked from knadh/listmonk
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from pankajsoni19/feature/traffic-split
Switch balancer to smoothed round robin, previous was inconsistent
- Loading branch information
Showing
12 changed files
with
173 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package balancer | ||
|
||
// Code is from https://github.com/mr-karan/balance | ||
// Updated for our usecase | ||
|
||
import ( | ||
"errors" | ||
"sync" | ||
) | ||
|
||
// ErrDuplicateID error is thrown when attempt to add an ID | ||
// which is already added to the balancer. | ||
var ErrDuplicateID = errors.New("entry already added") | ||
|
||
// Item represents the item in the list. | ||
type item struct { | ||
// id is the id of the item. | ||
id string | ||
// weight is the weight of the item that is given by the user. | ||
weight int | ||
// current is the current weight of the item. | ||
current int | ||
} | ||
|
||
// Balance represents a smooth weighted round-robin load balancer. | ||
type Balance struct { | ||
// items is the list of items to balance | ||
items []*item | ||
// next is the index of the next item to use. | ||
next *item | ||
|
||
mutex *sync.RWMutex | ||
|
||
ids []string | ||
} | ||
|
||
// NewBalance creates a new load balancer. | ||
func NewBalance() *Balance { | ||
return &Balance{ | ||
items: make([]*item, 0), | ||
mutex: &sync.RWMutex{}, | ||
} | ||
} | ||
|
||
// Allow chaining | ||
func (b *Balance) Add(id string, weight int) *Balance { | ||
b.mutex.Lock() | ||
defer b.mutex.Unlock() | ||
for _, v := range b.items { | ||
if v.id == id { | ||
return b | ||
} | ||
} | ||
|
||
b.items = append(b.items, &item{ | ||
id: id, | ||
weight: weight, | ||
current: 0, | ||
}) | ||
|
||
b.ids = append(b.ids, id) | ||
|
||
return b | ||
} | ||
|
||
func (b *Balance) All() []string { | ||
return b.ids | ||
} | ||
|
||
func (b *Balance) Get() string { | ||
b.mutex.Lock() | ||
defer b.mutex.Unlock() | ||
|
||
if len(b.items) == 0 { | ||
return "" | ||
} | ||
|
||
if len(b.items) == 1 { | ||
return b.items[0].id | ||
} | ||
|
||
// Total weight of all items. | ||
var total int | ||
|
||
// Loop through the list of items and add the item's weight to the current weight. | ||
// Also increment the total weight counter. | ||
var max *item | ||
for _, item := range b.items { | ||
item.current += item.weight | ||
total += item.weight | ||
|
||
// Select the item with max weight. | ||
if max == nil || item.current > max.current { | ||
max = item | ||
} | ||
} | ||
|
||
// Select the item with the max weight. | ||
b.next = max | ||
// Reduce the current weight of the selected item by the total weight. | ||
max.current -= total | ||
|
||
return max.id | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.