@@ -13,7 +13,8 @@ import (
13
13
"github.com/uber/cadence/common/log"
14
14
"github.com/uber/cadence/common/log/tag"
15
15
"github.com/uber/cadence/service/sharddistributor/config"
16
- "github.com/uber/cadence/service/sharddistributor/leader/leaderstore"
16
+ "github.com/uber/cadence/service/sharddistributor/leader/process"
17
+ "github.com/uber/cadence/service/sharddistributor/leader/store"
17
18
)
18
19
19
20
//go:generate mockgen -package $GOPACKAGE -source $GOFILE -destination=election_mock.go Factory,Elector
@@ -30,7 +31,7 @@ type ProcessFunc func(ctx context.Context) error
30
31
31
32
// Elector handles leader election for a specific namespace
32
33
type Elector interface {
33
- Run (ctx context.Context , OnLeader , OnResign ProcessFunc ) <- chan bool
34
+ Run (ctx context.Context ) <- chan bool
34
35
}
35
36
36
37
// Factory creates elector instances
@@ -39,60 +40,64 @@ type Factory interface {
39
40
}
40
41
41
42
type electionFactory struct {
42
- hostname string
43
- cfg config.Election
44
- store leaderstore.Store
45
- logger log.Logger
46
- serviceID string
47
- clock clock.TimeSource
43
+ hostname string
44
+ cfg config.Election
45
+ store store.Elector
46
+ logger log.Logger
47
+ serviceID string
48
+ clock clock.TimeSource
49
+ processFactory process.Factory
48
50
}
49
51
50
52
type elector struct {
51
- hostname string
52
- namespace string
53
- store leaderstore.Store
54
- logger log.Logger
55
- cfg config.Election
56
- leaderStarted time.Time
57
- clock clock.TimeSource
53
+ hostname string
54
+ namespace string
55
+ store store.Elector
56
+ logger log.Logger
57
+ cfg config.Election
58
+ leaderStarted time.Time
59
+ clock clock.TimeSource
60
+ processFactory process.Factory
58
61
}
59
62
60
63
type FactoryParams struct {
61
64
fx.In
62
65
63
- HostName string `name:"hostname"`
64
- Cfg config.LeaderElection
65
- Store leaderstore.Store
66
- Logger log.Logger
67
- Clock clock.TimeSource
66
+ HostName string `name:"hostname"`
67
+ Cfg config.LeaderElection
68
+ Store store.Elector
69
+ Logger log.Logger
70
+ Clock clock.TimeSource
71
+ ProcessFactory process.Factory
68
72
}
69
73
70
74
// NewElectionFactory creates a new election factory
71
75
func NewElectionFactory (p FactoryParams ) Factory {
72
76
return & electionFactory {
73
- cfg : p .Cfg .Election ,
74
- store : p .Store ,
75
- logger : p .Logger ,
76
- clock : p .Clock ,
77
- hostname : p .HostName ,
77
+ cfg : p .Cfg .Election ,
78
+ store : p .Store ,
79
+ logger : p .Logger ,
80
+ clock : p .Clock ,
81
+ hostname : p .HostName ,
82
+ processFactory : p .ProcessFactory ,
78
83
}
79
84
}
80
85
81
86
// CreateElector creates a new elector for the given namespace
82
87
func (f * electionFactory ) CreateElector (ctx context.Context , namespace string ) (Elector , error ) {
83
88
return & elector {
84
- namespace : namespace ,
85
- store : f .store ,
86
- logger : f .logger .WithTags (tag .ComponentLeaderElection , tag .ShardNamespace (namespace )),
87
- cfg : f .cfg ,
88
- clock : f .clock ,
89
- hostname : f .hostname ,
89
+ namespace : namespace ,
90
+ store : f .store ,
91
+ logger : f .logger .WithTags (tag .ComponentLeaderElection , tag .ShardNamespace (namespace )),
92
+ cfg : f .cfg ,
93
+ clock : f .clock ,
94
+ hostname : f .hostname ,
95
+ processFactory : f .processFactory ,
90
96
}, nil
91
97
}
92
98
93
99
// Run starts the leader election process it returns a channel that will return the value if the current instance becomes the leader or resigns from leadership.
94
- // OnLeader will be called once leadership is acquired. OnResign will be called once leadership is lost.
95
- func (e * elector ) Run (ctx context.Context , OnLeader , OnResign ProcessFunc ) <- chan bool {
100
+ func (e * elector ) Run (ctx context.Context ) <- chan bool {
96
101
leaderCh := make (chan bool , 1 )
97
102
98
103
// Create a child context that we can explicitly cancel when errors occur
@@ -108,7 +113,7 @@ func (e *elector) Run(ctx context.Context, OnLeader, OnResign ProcessFunc) <-cha
108
113
}()
109
114
110
115
for {
111
- if err := e .runElection (runCtx , leaderCh , OnLeader , OnResign ); err != nil {
116
+ if err := e .runElection (runCtx , leaderCh ); err != nil {
112
117
// Check if parent context is already canceled
113
118
if runCtx .Err () != nil {
114
119
e .logger .Info ("Context canceled, stopping election loop" , tag .Error (runCtx .Err ()))
@@ -137,7 +142,7 @@ func (e *elector) Run(ctx context.Context, OnLeader, OnResign ProcessFunc) <-cha
137
142
}
138
143
139
144
// runElection runs a single election attempt
140
- func (e * elector ) runElection (ctx context.Context , leaderCh chan <- bool , OnLeader , OnResign ProcessFunc ) (err error ) {
145
+ func (e * elector ) runElection (ctx context.Context , leaderCh chan <- bool ) (err error ) {
141
146
// Add random delay before campaigning to spread load across instances
142
147
delay := time .Duration (rand .Intn (int (e .cfg .MaxRandomDelay )))
143
148
@@ -150,12 +155,14 @@ func (e *elector) runElection(ctx context.Context, leaderCh chan<- bool, OnLeade
150
155
return fmt .Errorf ("context cancelled during pre-campaign delay: %w" , ctx .Err ())
151
156
}
152
157
158
+ leaderProcess := e .processFactory .CreateProcessor (e .namespace )
159
+
153
160
election , err := e .store .CreateElection (ctx , e .namespace )
154
161
if err != nil {
155
162
return fmt .Errorf ("create session: %w" , err )
156
163
}
157
164
defer func () {
158
- resignErr := e .resign (election , OnResign )
165
+ resignErr := e .resign (election , leaderProcess . Terminate )
159
166
if resignErr != nil {
160
167
if err == nil {
161
168
err = resignErr
@@ -175,7 +182,7 @@ func (e *elector) runElection(ctx context.Context, leaderCh chan<- bool, OnLeade
175
182
return fmt .Errorf ("failed to campaign: %w" , err )
176
183
}
177
184
178
- err = OnLeader (ctx )
185
+ err = leaderProcess . Run (ctx )
179
186
if err != nil {
180
187
return fmt .Errorf ("onLeader: %w" , err )
181
188
}
@@ -207,7 +214,7 @@ func (e *elector) runElection(ctx context.Context, leaderCh chan<- bool, OnLeade
207
214
}
208
215
}
209
216
210
- func (e * elector ) resign (election leaderstore .Election , onResign ProcessFunc ) error {
217
+ func (e * elector ) resign (election store .Election , onResign ProcessFunc ) error {
211
218
ctx , cancel := e .clock .ContextWithTimeout (context .Background (), 3 * time .Second )
212
219
defer cancel ()
213
220
0 commit comments