chore: 初始化 Cloudreve 源码仓库
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package balancer
|
||||
|
||||
type Balancer interface {
|
||||
NextPeer(nodes interface{}) (error, interface{})
|
||||
}
|
||||
|
||||
// NewBalancer 根据策略标识返回新的负载均衡器
|
||||
func NewBalancer(strategy string) Balancer {
|
||||
switch strategy {
|
||||
case "RoundRobin":
|
||||
return &RoundRobin{}
|
||||
default:
|
||||
return &RoundRobin{}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package balancer
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBalancer(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
a.NotNil(NewBalancer(""))
|
||||
a.IsType(&RoundRobin{}, NewBalancer("RoundRobin"))
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package balancer
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrInputNotSlice = errors.New("Input value is not silice")
|
||||
ErrNoAvaliableNode = errors.New("No nodes avaliable")
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
package balancer
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type RoundRobin struct {
|
||||
current uint64
|
||||
}
|
||||
|
||||
// NextPeer 返回轮盘的下一节点
|
||||
func (r *RoundRobin) NextPeer(nodes interface{}) (error, interface{}) {
|
||||
v := reflect.ValueOf(nodes)
|
||||
if v.Kind() != reflect.Slice {
|
||||
return ErrInputNotSlice, nil
|
||||
}
|
||||
|
||||
if v.Len() == 0 {
|
||||
return ErrNoAvaliableNode, nil
|
||||
}
|
||||
|
||||
next := r.NextIndex(v.Len())
|
||||
return nil, v.Index(next).Interface()
|
||||
}
|
||||
|
||||
// NextIndex 返回下一个节点下标
|
||||
func (r *RoundRobin) NextIndex(total int) int {
|
||||
return int(atomic.AddUint64(&r.current, uint64(1)) % uint64(total))
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package balancer
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRoundRobin_NextIndex(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
r := &RoundRobin{}
|
||||
total := 5
|
||||
for i := 1; i < total; i++ {
|
||||
a.Equal(i, r.NextIndex(total))
|
||||
}
|
||||
for i := 0; i < total; i++ {
|
||||
a.Equal(i, r.NextIndex(total))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundRobin_NextPeer(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
r := &RoundRobin{}
|
||||
|
||||
// not slice
|
||||
{
|
||||
err, _ := r.NextPeer("s")
|
||||
a.Equal(ErrInputNotSlice, err)
|
||||
}
|
||||
|
||||
// no nodes
|
||||
{
|
||||
err, _ := r.NextPeer([]string{})
|
||||
a.Equal(ErrNoAvaliableNode, err)
|
||||
}
|
||||
|
||||
// pass
|
||||
{
|
||||
err, res := r.NextPeer([]string{"a"})
|
||||
a.NoError(err)
|
||||
a.Equal("a", res.(string))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user