-
Notifications
You must be signed in to change notification settings - Fork 182
/
selector.go
125 lines (100 loc) · 2.51 KB
/
selector.go
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package common
import (
"errors"
"sort"
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
)
var (
errDuplicateVersionSelector = errors.New("duplicate version ")
errRepeatRegisterSelector = errors.New("repeat register selectors ")
)
var (
DefaultFactory = func(higherThan func(h int64) bool, version SelectVersion, internal interface{}) SelectorFactory {
return func() Selector {
return NewCommonHeightSelector(higherThan, version, internal)
}
}
)
// TODO,use genesis
type Selector interface {
Version() SelectVersion
Select(ctx sdk.Context) (interface{}, bool)
}
type SelectVersion float64
type SelectorFactory func() Selector
type Selectors []Selector
func (m Selectors) Len() int {
return len(m)
}
func (m Selectors) Less(i, j int) bool {
return m[i].Version() >= m[j].Version()
}
func (m Selectors) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}
////////
var (
_ Selector = (*CommonHeightSelector)(nil)
)
type CommonHeightSelector struct {
higherThan func(h int64) bool
version SelectVersion
internal interface{}
}
func NewCommonHeightSelector(higherThan func(h int64) bool, version SelectVersion, internal interface{}) *CommonHeightSelector {
return &CommonHeightSelector{higherThan: higherThan, version: version, internal: internal}
}
func (c *CommonHeightSelector) Version() SelectVersion {
return c.version
}
func (c *CommonHeightSelector) Select(ctx sdk.Context) (interface{}, bool) {
if c.higherThan(ctx.BlockHeight()) {
return c.internal, true
}
return nil, false
}
///////
type SelectorStrategy struct {
internal interface{}
selectors Selectors
seal bool
}
func (f *SelectorStrategy) RegisterSelectors(factories ...SelectorFactory) {
if f.Seald() {
panic(errDuplicateVersionSelector)
}
var selectors Selectors
set := make(map[SelectVersion]struct{})
for _, f := range factories {
sel := f()
selectors = append(selectors, sel)
v := sel.Version()
if _, contains := set[v]; contains {
panic(errDuplicateVersionSelector)
}
set[v] = struct{}{}
}
sort.Sort(selectors)
f.selectors = selectors
}
func NewSelectorStrategy(internal interface{}) *SelectorStrategy {
return &SelectorStrategy{internal: internal}
}
func (f *SelectorStrategy) Seald() bool {
return f.seal
}
func (f *SelectorStrategy) Seal() {
f.seal = true
}
func (f *SelectorStrategy) GetProxy(ctx sdk.Context) interface{} {
for _, s := range f.selectors {
m, ok := s.Select(ctx)
if ok {
return m
}
}
return f.internal
}
func (f *SelectorStrategy) GetInternal() interface{} {
return f.internal
}