[#1208] innerring: Disallow to tick timer twice on the same height
Provide current heights as an argument to ticker. Zero height disables any checks, thus corresponding to the old behaviour. If non-zero height is used, ignore the tick if the height is less than the timer tick state. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
c0e65dadaf
commit
4770cb8bf6
4 changed files with 68 additions and 8 deletions
|
@ -66,9 +66,9 @@ func (s *Server) startBlockTimers() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) tickTimers() {
|
func (s *Server) tickTimers(h uint32) {
|
||||||
for i := range s.blockTimers {
|
for i := range s.blockTimers {
|
||||||
s.blockTimers[i].Tick()
|
s.blockTimers[i].Tick(h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
|
||||||
zap.Uint32("block_index", b.Index))
|
zap.Uint32("block_index", b.Index))
|
||||||
}
|
}
|
||||||
|
|
||||||
s.tickTimers()
|
s.tickTimers(b.Index)
|
||||||
})
|
})
|
||||||
|
|
||||||
if !s.withoutMainNet {
|
if !s.withoutMainNet {
|
||||||
|
|
|
@ -27,6 +27,8 @@ type BlockTimer struct {
|
||||||
|
|
||||||
cur, tgt uint32
|
cur, tgt uint32
|
||||||
|
|
||||||
|
last uint32
|
||||||
|
|
||||||
h BlockTickHandler
|
h BlockTickHandler
|
||||||
|
|
||||||
ps []BlockTimer
|
ps []BlockTimer
|
||||||
|
@ -159,13 +161,18 @@ func (t *BlockTimer) reset() {
|
||||||
// Tick ticks one block in the BlockTimer.
|
// Tick ticks one block in the BlockTimer.
|
||||||
//
|
//
|
||||||
// Executes all callbacks which are awaiting execution at the new block.
|
// Executes all callbacks which are awaiting execution at the new block.
|
||||||
func (t *BlockTimer) Tick() {
|
func (t *BlockTimer) Tick(h uint32) {
|
||||||
t.mtx.Lock()
|
t.mtx.Lock()
|
||||||
t.tick()
|
t.tick(h)
|
||||||
t.mtx.Unlock()
|
t.mtx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BlockTimer) tick() {
|
func (t *BlockTimer) tick(h uint32) {
|
||||||
|
if h != 0 && t.last == h {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.last = h
|
||||||
t.cur++
|
t.cur++
|
||||||
|
|
||||||
if t.cur == t.tgt {
|
if t.cur == t.tgt {
|
||||||
|
@ -182,6 +189,6 @@ func (t *BlockTimer) tick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range t.ps {
|
for i := range t.ps {
|
||||||
t.ps[i].tick()
|
t.ps[i].tick(h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
func tickN(t *timer.BlockTimer, n uint32) {
|
func tickN(t *timer.BlockTimer, n uint32) {
|
||||||
for i := uint32(0); i < n; i++ {
|
for i := uint32(0); i < n; i++ {
|
||||||
t.Tick()
|
t.Tick(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,3 +159,56 @@ func TestNewOneTickTimer(t *testing.T) {
|
||||||
require.Equal(t, 1, detlaCallCounter)
|
require.Equal(t, 1, detlaCallCounter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBlockTimer_TickSameHeight(t *testing.T) {
|
||||||
|
var baseCounter, deltaCounter int
|
||||||
|
|
||||||
|
blockDur := uint32(2)
|
||||||
|
bt := timer.NewBlockTimer(
|
||||||
|
func() (uint32, error) { return blockDur, nil },
|
||||||
|
func() { baseCounter++ })
|
||||||
|
bt.OnDelta(2, 1, func() {
|
||||||
|
deltaCounter++
|
||||||
|
})
|
||||||
|
require.NoError(t, bt.Reset())
|
||||||
|
|
||||||
|
check := func(t *testing.T, h uint32, base, delta int) {
|
||||||
|
for i := 0; i < 2*int(blockDur); i++ {
|
||||||
|
bt.Tick(h)
|
||||||
|
require.Equal(t, base, baseCounter)
|
||||||
|
require.Equal(t, delta, deltaCounter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check(t, 1, 0, 0)
|
||||||
|
check(t, 2, 1, 0)
|
||||||
|
check(t, 3, 1, 0)
|
||||||
|
check(t, 4, 2, 1)
|
||||||
|
|
||||||
|
t.Run("works the same way after `Reset()`", func(t *testing.T) {
|
||||||
|
t.Run("same block duration", func(t *testing.T) {
|
||||||
|
require.NoError(t, bt.Reset())
|
||||||
|
baseCounter = 0
|
||||||
|
deltaCounter = 0
|
||||||
|
|
||||||
|
check(t, 1, 0, 0)
|
||||||
|
check(t, 2, 1, 0)
|
||||||
|
check(t, 3, 1, 0)
|
||||||
|
check(t, 4, 2, 1)
|
||||||
|
})
|
||||||
|
t.Run("different block duration", func(t *testing.T) {
|
||||||
|
blockDur = 3
|
||||||
|
|
||||||
|
require.NoError(t, bt.Reset())
|
||||||
|
baseCounter = 0
|
||||||
|
deltaCounter = 0
|
||||||
|
|
||||||
|
check(t, 1, 0, 0)
|
||||||
|
check(t, 2, 0, 0)
|
||||||
|
check(t, 3, 1, 0)
|
||||||
|
check(t, 4, 1, 0)
|
||||||
|
check(t, 5, 1, 0)
|
||||||
|
check(t, 6, 2, 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue