...
1
17
18 package wrr
19
20 import (
21 "fmt"
22 "sort"
23
24 "google.golang.org/grpc/internal/grpcrand"
25 )
26
27
28 type weightedItem struct {
29 item any
30 weight int64
31 accumulatedWeight int64
32 }
33
34 func (w *weightedItem) String() string {
35 return fmt.Sprint(*w)
36 }
37
38
39 type randomWRR struct {
40 items []*weightedItem
41
42 equalWeights bool
43 }
44
45
46 func NewRandom() WRR {
47 return &randomWRR{}
48 }
49
50 var grpcrandInt63n = grpcrand.Int63n
51
52 func (rw *randomWRR) Next() (item any) {
53 if len(rw.items) == 0 {
54 return nil
55 }
56 if rw.equalWeights {
57 return rw.items[grpcrandInt63n(int64(len(rw.items)))].item
58 }
59
60 sumOfWeights := rw.items[len(rw.items)-1].accumulatedWeight
61
62 randomWeight := grpcrandInt63n(sumOfWeights)
63
64
65
66 i := sort.Search(len(rw.items), func(i int) bool { return rw.items[i].accumulatedWeight > randomWeight })
67 return rw.items[i].item
68 }
69
70 func (rw *randomWRR) Add(item any, weight int64) {
71 accumulatedWeight := weight
72 equalWeights := true
73 if len(rw.items) > 0 {
74 lastItem := rw.items[len(rw.items)-1]
75 accumulatedWeight = lastItem.accumulatedWeight + weight
76 equalWeights = rw.equalWeights && weight == lastItem.weight
77 }
78 rw.equalWeights = equalWeights
79 rItem := &weightedItem{item: item, weight: weight, accumulatedWeight: accumulatedWeight}
80 rw.items = append(rw.items, rItem)
81 }
82
83 func (rw *randomWRR) String() string {
84 return fmt.Sprint(rw.items)
85 }
86
View as plain text