@@ -28,25 +28,21 @@ func GetTimerFunc() TimerFunc {
2828 return func (duty core.Duty ) RoundTimer {
2929 // Linear timer only affects Proposer duty
3030 if duty .Type == core .DutyProposer {
31- return NewLinearRoundTimer ( )
31+ return NewLinearRoundTimerWithDuty ( duty )
3232 } else if featureset .Enabled (featureset .EagerDoubleLinear ) {
33- return NewDoubleEagerLinearRoundTimer ( )
33+ return NewDoubleEagerLinearRoundTimerWithDuty ( duty )
3434 }
3535
36- return NewIncreasingRoundTimer ( )
36+ return NewIncreasingRoundTimerWithDuty ( duty )
3737 }
3838 }
3939
4040 if featureset .Enabled (featureset .EagerDoubleLinear ) {
41- return func (core.Duty ) RoundTimer {
42- return NewDoubleEagerLinearRoundTimer ()
43- }
41+ return NewDoubleEagerLinearRoundTimerWithDuty
4442 }
4543
4644 // Default to increasing round timer.
47- return func (core.Duty ) RoundTimer {
48- return NewIncreasingRoundTimer ()
49- }
45+ return NewIncreasingRoundTimerWithDuty
5046}
5147
5248// TimerType is the type of round timer.
@@ -82,6 +78,12 @@ type RoundTimer interface {
8278 Type () TimerType
8379}
8480
81+ // proposalTimeoutOptimization returns true if ProposalTimeout feature is enabled, the duty is proposer and
82+ // we are in the first round.
83+ func proposalTimeoutOptimization (duty core.Duty , round int64 ) bool {
84+ return featureset .Enabled (featureset .ProposalTimeout ) && duty .Type == core .DutyProposer && round == 1
85+ }
86+
8587// NewTimeoutRoundTimer returns a new increasing round timer type.
8688func NewIncreasingRoundTimer () RoundTimer {
8789 return NewIncreasingRoundTimerWithClock (clockwork .NewRealClock ())
@@ -94,17 +96,40 @@ func NewIncreasingRoundTimerWithClock(clock clockwork.Clock) RoundTimer {
9496 }
9597}
9698
99+ // NewIncreasingRoundTimerWithDuty returns a new eager double linear round timer type for a specific duty.
100+ func NewIncreasingRoundTimerWithDuty (duty core.Duty ) RoundTimer {
101+ return & increasingRoundTimer {
102+ clock : clockwork .NewRealClock (),
103+ duty : duty ,
104+ }
105+ }
106+
107+ // NewIncreasingRoundTimerWithDuty returns a new eager double linear round timer type for a specific duty and custom clock.
108+ func NewIncreasingRoundTimerWithDutyAndClock (duty core.Duty , clock clockwork.Clock ) RoundTimer {
109+ return & increasingRoundTimer {
110+ clock : clock ,
111+ duty : duty ,
112+ }
113+ }
114+
97115// increasingRoundTimer implements a linear increasing round timerType.
98116type increasingRoundTimer struct {
99117 clock clockwork.Clock
118+ duty core.Duty
100119}
101120
102121func (increasingRoundTimer ) Type () TimerType {
103122 return TimerIncreasing
104123}
105124
106125func (t increasingRoundTimer ) Timer (round int64 ) (<- chan time.Time , func ()) {
107- timer := t .clock .NewTimer (increasingRoundTimeout (round ))
126+ timeout := increasingRoundTimeout (round )
127+ if proposalTimeoutOptimization (t .duty , round ) {
128+ timeout = 1500 * time .Millisecond
129+ }
130+
131+ timer := t .clock .NewTimer (timeout )
132+
108133 return timer .Chan (), func () { timer .Stop () }
109134}
110135
@@ -121,6 +146,24 @@ func NewDoubleEagerLinearRoundTimerWithClock(clock clockwork.Clock) RoundTimer {
121146 }
122147}
123148
149+ // NewDoubleEagerLinearRoundTimerWithDuty returns a new eager double linear round timer type for a specific duty.
150+ func NewDoubleEagerLinearRoundTimerWithDuty (duty core.Duty ) RoundTimer {
151+ return & doubleEagerLinearRoundTimer {
152+ clock : clockwork .NewRealClock (),
153+ duty : duty ,
154+ firstDeadlines : make (map [int64 ]time.Time ),
155+ }
156+ }
157+
158+ // NewDoubleEagerLinearRoundTimerWithDutyAndClock returns a new eager double linear round timer type for a specific duty and custom clock.
159+ func NewDoubleEagerLinearRoundTimerWithDutyAndClock (duty core.Duty , clock clockwork.Clock ) RoundTimer {
160+ return & doubleEagerLinearRoundTimer {
161+ clock : clock ,
162+ duty : duty ,
163+ firstDeadlines : make (map [int64 ]time.Time ),
164+ }
165+ }
166+
124167// doubleEagerLinearRoundTimer implements a round timerType with the following properties:
125168//
126169// It doubles the round duration when a leader is active.
@@ -137,6 +180,7 @@ func NewDoubleEagerLinearRoundTimerWithClock(clock clockwork.Clock) RoundTimer {
137180// It is linear, meaning the round duration increases linearly with the round number: 1s, 2s, 3s, etc.
138181type doubleEagerLinearRoundTimer struct {
139182 clock clockwork.Clock
183+ duty core.Duty
140184
141185 mu sync.Mutex
142186 firstDeadlines map [int64 ]time.Time
@@ -150,13 +194,20 @@ func (t *doubleEagerLinearRoundTimer) Timer(round int64) (<-chan time.Time, func
150194 t .mu .Lock ()
151195 defer t .mu .Unlock ()
152196
197+ var timeout time.Duration
198+ if proposalTimeoutOptimization (t .duty , round ) {
199+ timeout = 1500 * time .Millisecond
200+ } else {
201+ timeout = linearRoundTimeout (round )
202+ }
203+
153204 var deadline time.Time
154205 if first , ok := t .firstDeadlines [round ]; ok {
155206 // Deadline is either double the first timeout
156- deadline = first .Add (linearRoundTimeout ( round ) )
207+ deadline = first .Add (timeout )
157208 } else {
158209 // Or the first timeout
159- deadline = t .clock .Now ().Add (linearRoundTimeout ( round ) )
210+ deadline = t .clock .Now ().Add (timeout )
160211 t .firstDeadlines [round ] = deadline
161212 }
162213
@@ -173,22 +224,27 @@ func (t *doubleEagerLinearRoundTimer) Timer(round int64) (<-chan time.Time, func
173224// which will increase linearly
174225type linearRoundTimer struct {
175226 clock clockwork.Clock
227+ duty core.Duty
176228}
177229
178230func (* linearRoundTimer ) Type () TimerType {
179231 return TimerLinear
180232}
181233
182234func (t * linearRoundTimer ) Timer (round int64 ) (<- chan time.Time , func ()) {
183- var timer clockwork.Timer
184- if round == 1 {
235+ var timeout time.Duration
236+ if proposalTimeoutOptimization (t .duty , round ) {
237+ timeout = 1500 * time .Millisecond
238+ } else if round == 1 {
185239 // First round has 1 second
186- timer = t . clock . NewTimer ( time .Second )
240+ timeout = time .Second
187241 } else {
188242 // Subsequent rounds have linearly more time starting at 400 milliseconds
189- timer = t . clock . NewTimer ( time .Duration (200 * (round - 1 ) + 200 ) )
243+ timeout = time .Duration (200 * (round - 1 ) + 200 )
190244 }
191245
246+ timer := t .clock .NewTimer (timeout )
247+
192248 return timer .Chan (), func () { timer .Stop () }
193249}
194250
@@ -197,8 +253,25 @@ func NewLinearRoundTimer() RoundTimer {
197253 return NewLinearRoundTimerWithClock (clockwork .NewRealClock ())
198254}
199255
256+ // NewLinearRoundTimerWithClock returns a new linear round timer type with a custom clock.
200257func NewLinearRoundTimerWithClock (clock clockwork.Clock ) RoundTimer {
201258 return & linearRoundTimer {
202259 clock : clock ,
203260 }
204261}
262+
263+ // NewLinearRoundTimerWithDuty returns a new linear round timer type for a specific duty.
264+ func NewLinearRoundTimerWithDuty (duty core.Duty ) RoundTimer {
265+ return & linearRoundTimer {
266+ clock : clockwork .NewRealClock (),
267+ duty : duty ,
268+ }
269+ }
270+
271+ // NewLinearRoundTimerWithDutyAndClock returns a new linear round timer type for a specific duty and custom clock.
272+ func NewLinearRoundTimerWithDutyAndClock (duty core.Duty , clock clockwork.Clock ) RoundTimer {
273+ return & linearRoundTimer {
274+ clock : clock ,
275+ duty : duty ,
276+ }
277+ }
0 commit comments