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{}) }, ) }