62 lines
1.2 KiB
Go
62 lines
1.2 KiB
Go
package routing
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
type Sequential struct {
|
|
mu sync.RWMutex
|
|
upstreams []string
|
|
threshold int
|
|
current int
|
|
empty map[string]int
|
|
}
|
|
|
|
func NewSequential(upstreams []string, threshold int) (*Sequential, error) {
|
|
if len(upstreams) == 0 {
|
|
return nil, fmt.Errorf("sequential strategy requires at least one upstream")
|
|
}
|
|
if threshold <= 0 {
|
|
return nil, fmt.Errorf("sequential threshold must be greater than zero")
|
|
}
|
|
return &Sequential{
|
|
upstreams: append([]string(nil), upstreams...),
|
|
threshold: threshold,
|
|
empty: make(map[string]int, len(upstreams)),
|
|
}, nil
|
|
}
|
|
|
|
func (s *Sequential) Current() string {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
return s.upstreams[s.current]
|
|
}
|
|
|
|
func (s *Sequential) ObserveEmpty(upstream string) bool {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
s.empty[upstream]++
|
|
if s.upstreams[s.current] != upstream || s.empty[upstream] < s.threshold {
|
|
return false
|
|
}
|
|
if s.current+1 >= len(s.upstreams) {
|
|
return false
|
|
}
|
|
s.current++
|
|
return true
|
|
}
|
|
|
|
func (s *Sequential) ObserveValid(upstream string) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.empty[upstream] = 0
|
|
}
|
|
|
|
func (s *Sequential) EmptyCount(upstream string) int {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
return s.empty[upstream]
|
|
}
|