frostfs-node/pkg/innerring/blocktimer.go
Dmitrii Stepanov 53693071de [#280] ir: Add block timer unit tests
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2023-05-02 08:48:07 +00:00

125 lines
2.9 KiB
Go

package innerring
import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"github.com/nspcc-dev/neo-go/pkg/util"
"go.uber.org/zap"
)
type (
epochState interface {
EpochCounter() uint64
EpochDuration() uint64
}
alphaState interface {
IsAlphabet() bool
}
newEpochHandler func()
containerEstimationStopper interface {
StopEstimation(p container.StopEstimationPrm) error
}
epochTimerArgs struct {
l *logger.Logger
alphabetState alphaState
newEpochHandlers []newEpochHandler
cnrWrapper containerEstimationStopper // to invoke stop container estimation
epoch epochState // to specify which epoch to stop, and epoch duration
stopEstimationDMul uint32 // X: X/Y of epoch in blocks
stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks
}
emitTimerArgs struct {
ap *alphabet.Processor // to handle new emission tick
emitDuration uint32 // in blocks
}
depositor func() (util.Uint256, error)
awaiter func(context.Context, util.Uint256) error
)
func (s *Server) addBlockTimer(t *timer.BlockTimer) {
s.blockTimers = append(s.blockTimers, t)
}
func (s *Server) startBlockTimers() error {
for i := range s.blockTimers {
if err := s.blockTimers[i].Reset(); err != nil {
return err
}
}
return nil
}
func (s *Server) tickTimers(h uint32) {
for i := range s.blockTimers {
s.blockTimers[i].Tick(h)
}
}
func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
epochTimer := timer.NewBlockTimer(
func() (uint32, error) {
return uint32(args.epoch.EpochDuration()), nil
},
func() {
for _, handler := range args.newEpochHandlers {
handler()
}
},
)
// sub-timer for epoch timer to tick stop container estimation events at
// some block in epoch
epochTimer.OnDelta(
args.stopEstimationDMul,
args.stopEstimationDDiv,
func() {
if !args.alphabetState.IsAlphabet() {
args.l.Debug(logs.InnerringNonalphabetModeDoNotStopContainerEstimations)
return
}
epochN := args.epoch.EpochCounter()
if epochN == 0 { // estimates are invalid in genesis epoch
return
}
prm := container.StopEstimationPrm{}
prm.SetEpoch(epochN - 1)
err := args.cnrWrapper.StopEstimation(prm)
if err != nil {
args.l.Warn(logs.InnerringCantStopEpochEstimation,
zap.Uint64("epoch", epochN),
zap.String("error", err.Error()))
}
})
return epochTimer
}
func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer {
return timer.NewBlockTimer(
timer.StaticBlockMeter(args.emitDuration),
func() {
args.ap.HandleGasEmission(timerEvent.NewAlphabetEmitTick{})
},
)
}