[#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>
neofs-adm-notary-disabled
Evgenii Stratonikov 2022-03-30 13:16:41 +03:00 committed by Alex Vanin
parent c0e65dadaf
commit 4770cb8bf6
4 changed files with 68 additions and 8 deletions

View File

@ -66,9 +66,9 @@ func (s *Server) startBlockTimers() error {
return nil
}
func (s *Server) tickTimers() {
func (s *Server) tickTimers(h uint32) {
for i := range s.blockTimers {
s.blockTimers[i].Tick()
s.blockTimers[i].Tick(h)
}
}

View File

@ -241,7 +241,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
zap.Uint32("block_index", b.Index))
}
s.tickTimers()
s.tickTimers(b.Index)
})
if !s.withoutMainNet {

View File

@ -27,6 +27,8 @@ type BlockTimer struct {
cur, tgt uint32
last uint32
h BlockTickHandler
ps []BlockTimer
@ -159,13 +161,18 @@ func (t *BlockTimer) reset() {
// Tick ticks one block in the BlockTimer.
//
// 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.tick()
t.tick(h)
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++
if t.cur == t.tgt {
@ -182,6 +189,6 @@ func (t *BlockTimer) tick() {
}
for i := range t.ps {
t.ps[i].tick()
t.ps[i].tick(h)
}
}

View File

@ -9,7 +9,7 @@ import (
func tickN(t *timer.BlockTimer, n uint32) {
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)
})
}
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)
})
})
}