aboutsummaryrefslogtreecommitdiff
path: root/plugin/pkg/policy/policy.go
blob: c5e9de6f49f8c71378cccb692aa271d3f425138d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package policy

import (
	"math/rand"
	"sync/atomic"
)

// Policy defines a policy we use for selecting upstreams.
type Policy interface {
	List(policy ...interface{}) []interface{}
	String() string
}

// Random is a policy that implements random upstream selection.
type Random struct{}

var _ Policy = &Random{}

// String returns the name of policy Random
func (r *Random) String() string { return "random" }

// List returns a set of proxies to be used for this client depending on Random policy.
func (r *Random) List(p ...interface{}) []interface{} {
	switch len(p) {
	case 1:
		return p
	case 2:
		if rand.Int()%2 == 0 {
			return []interface{}{p[1], p[0]} // swap
		}
		return p
	}

	perms := rand.Perm(len(p))
	rnd := make([]interface{}, len(p))

	for i, p1 := range perms {
		rnd[i] = p[p1]
	}
	return rnd
}

// RoundRobin is a policy that selects hosts based on round robin ordering.
type RoundRobin struct {
	robin uint32
}

var _ Policy = &RoundRobin{}

// String returns the name of policy RoundRobin
func (r *RoundRobin) String() string { return "round_robin" }

// List returns a set of proxies to be used for this client depending on RoundRobin policy.
func (r *RoundRobin) List(p ...interface{}) []interface{} {
	poolLen := uint32(len(p))
	i := atomic.AddUint32(&r.robin, 1) % poolLen

	robin := []interface{}{p[i]}
	robin = append(robin, p[:i]...)
	robin = append(robin, p[i+1:]...)

	return robin
}

// Sequential is a policy that selects hosts based on sequential ordering.
type Sequential struct{}

var _ Policy = &Sequential{}

// String returns the name of policy Sequential
func (r *Sequential) String() string { return "sequential" }

// List returns a set of proxies without filter.
func (r *Sequential) List(p ...interface{}) []interface{} {
	return p
}