Skip to content

Commit 65592e8

Browse files
committed
fixes
1 parent 394ecc5 commit 65592e8

File tree

4 files changed

+62
-72
lines changed

4 files changed

+62
-72
lines changed

block/components.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,11 @@ func NewSyncComponents(
178178
syncer.SetBlockSyncer(syncing.WithTracingBlockSyncer(syncer))
179179
}
180180

181-
var execPruner pruner.ExecMetaPruner
182-
if exec != nil {
183-
if candidate, ok := exec.(pruner.ExecMetaPruner); ok {
184-
execPruner = candidate
185-
}
181+
var execPruner pruner.ExecPruner
182+
if p, ok := exec.(pruner.ExecPruner); ok {
183+
execPruner = p
186184
}
187-
recoveryPruner := pruner.New(store, execPruner, config.Node.RecoveryHistoryDepth, pruner.DefaultPruneInterval, logger.With().Str("component", "Pruner").Logger())
185+
pruner := pruner.New(logger, store, execPruner, config.Node)
188186

189187
// Create submitter for sync nodes (no signer, only DA inclusion processing)
190188
var daSubmitter submitting.DASubmitterAPI = submitting.NewDASubmitter(daClient, config, genesis, blockOpts, metrics, logger, headerDAHintAppender, dataDAHintAppender)
@@ -209,7 +207,7 @@ func NewSyncComponents(
209207
Syncer: syncer,
210208
Submitter: submitter,
211209
Cache: cacheManager,
212-
Pruner: recoveryPruner,
210+
Pruner: pruner,
213211
errorCh: errorCh,
214212
}, nil
215213
}
@@ -269,13 +267,11 @@ func NewAggregatorComponents(
269267
executor.SetBlockProducer(executing.WithTracingBlockProducer(executor))
270268
}
271269

272-
var execPruner pruner.ExecMetaPruner
273-
if exec != nil {
274-
if candidate, ok := exec.(pruner.ExecMetaPruner); ok {
275-
execPruner = candidate
276-
}
270+
var execPruner pruner.ExecPruner
271+
if p, ok := exec.(pruner.ExecPruner); ok {
272+
execPruner = p
277273
}
278-
recoveryPruner := pruner.New(store, execPruner, config.Node.RecoveryHistoryDepth, pruner.DefaultPruneInterval, logger.With().Str("component", "Pruner").Logger())
274+
pruner := pruner.New(logger, store, execPruner, config.Node)
279275

280276
reaper, err := reaping.NewReaper(
281277
exec,
@@ -293,7 +289,7 @@ func NewAggregatorComponents(
293289
if config.Node.BasedSequencer { // no submissions needed for bases sequencer
294290
return &Components{
295291
Executor: executor,
296-
Pruner: recoveryPruner,
292+
Pruner: pruner,
297293
Reaper: reaper,
298294
Cache: cacheManager,
299295
errorCh: errorCh,
@@ -320,7 +316,7 @@ func NewAggregatorComponents(
320316

321317
return &Components{
322318
Executor: executor,
323-
Pruner: recoveryPruner,
319+
Pruner: pruner,
324320
Reaper: reaper,
325321
Submitter: submitter,
326322
Cache: cacheManager,

block/internal/pruner/pruner.go

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ import (
99
ds "github.com/ipfs/go-datastore"
1010
"github.com/rs/zerolog"
1111

12+
"github.com/evstack/ev-node/pkg/config"
1213
"github.com/evstack/ev-node/pkg/store"
1314
)
1415

1516
const (
16-
DefaultPruneInterval = 15 * time.Minute
17+
defaultPruneInterval = 15 * time.Minute
1718
// maxPruneBatch limits how many heights we prune per cycle to bound work.
1819
maxPruneBatch = uint64(1000)
1920
)
2021

21-
// ExecMetaPruner removes execution metadata at a given height.
22-
type ExecMetaPruner interface {
23-
PruneExecMeta(ctx context.Context, height uint64) error
22+
// ExecPruner removes execution metadata at a given height.
23+
type ExecPruner interface {
24+
PruneExec(ctx context.Context, height uint64) error
2425
}
2526

2627
type stateDeleter interface {
@@ -31,22 +32,24 @@ type stateDeleter interface {
3132
type Pruner struct {
3233
store store.Store
3334
stateDeleter stateDeleter
34-
execPruner ExecMetaPruner
35-
retention uint64
36-
interval time.Duration
35+
execPruner ExecPruner
36+
cfg config.NodeConfig
3737
logger zerolog.Logger
3838
lastPruned uint64
3939

40+
// Lifecycle
41+
ctx context.Context
4042
wg sync.WaitGroup
4143
cancel context.CancelFunc
4244
}
4345

4446
// New creates a new Pruner instance.
45-
func New(store store.Store, execMetaPruner ExecMetaPruner, retention uint64, interval time.Duration, logger zerolog.Logger) *Pruner {
46-
if interval <= 0 {
47-
interval = DefaultPruneInterval
48-
}
49-
47+
func New(
48+
logger zerolog.Logger,
49+
store store.Store,
50+
execPruner ExecPruner,
51+
cfg config.NodeConfig,
52+
) *Pruner {
5053
var deleter stateDeleter
5154
if store != nil {
5255
if sd, ok := store.(stateDeleter); ok {
@@ -57,75 +60,66 @@ func New(store store.Store, execMetaPruner ExecMetaPruner, retention uint64, int
5760
return &Pruner{
5861
store: store,
5962
stateDeleter: deleter,
60-
execPruner: execMetaPruner,
61-
retention: retention,
62-
interval: interval,
63-
logger: logger,
63+
execPruner: execPruner,
64+
cfg: cfg,
65+
logger: logger.With().Str("component", "prune").Logger(),
6466
}
6567
}
6668

6769
// Start begins the pruning loop.
6870
func (p *Pruner) Start(ctx context.Context) error {
69-
if p.retention == 0 {
70-
return nil
71-
}
71+
p.ctx, p.cancel = context.WithCancel(ctx)
7272

73-
loopCtx, cancel := context.WithCancel(ctx)
74-
p.cancel = cancel
75-
76-
p.wg.Add(1)
77-
go p.pruneLoop(loopCtx)
73+
// Start pruner loop
74+
p.wg.Go(p.pruneLoop)
7875

76+
p.logger.Info().Msg("pruner started")
7977
return nil
8078
}
8179

8280
// Stop stops the pruning loop.
8381
func (p *Pruner) Stop() error {
84-
if p == nil || p.cancel == nil {
85-
return nil
82+
if p.cancel != nil {
83+
p.cancel()
8684
}
87-
88-
p.cancel()
8985
p.wg.Wait()
86+
87+
p.logger.Info().Msg("pruner stopped")
9088
return nil
9189
}
9290

93-
func (p *Pruner) pruneLoop(ctx context.Context) {
94-
defer p.wg.Done()
95-
ticker := time.NewTicker(p.interval)
91+
func (p *Pruner) pruneLoop() {
92+
ticker := time.NewTicker(defaultPruneInterval)
9693
defer ticker.Stop()
9794

98-
if err := p.pruneOnce(ctx); err != nil {
99-
p.logger.Error().Err(err).Msg("failed to prune recovery history")
100-
}
101-
10295
for {
10396
select {
10497
case <-ticker.C:
105-
if err := p.pruneOnce(ctx); err != nil {
98+
if err := p.pruneRecoveryHistory(p.ctx, p.cfg.RecoveryHistoryDepth); err != nil {
10699
p.logger.Error().Err(err).Msg("failed to prune recovery history")
107100
}
108-
case <-ctx.Done():
101+
102+
// TODO: add pruning of old blocks // https://github.com/evstack/ev-node/pull/2984
103+
case <-p.ctx.Done():
109104
return
110105
}
111106
}
112107
}
113108

114-
func (p *Pruner) pruneOnce(ctx context.Context) error {
115-
if p.retention == 0 || p.store == nil {
116-
return nil
117-
}
118-
109+
// pruneRecoveryHistory prunes old state and execution metadata entries based on the configured retention depth.
110+
// It does not prunes old blocks, as those are handled by the pruning logic.
111+
// Pruning old state does not lose history but limit the ability to recover (replay or rollback) to the last HEAD-N blocks, where N is the retention depth.
112+
func (p *Pruner) pruneRecoveryHistory(ctx context.Context, retention uint64) error {
119113
height, err := p.store.Height(ctx)
120114
if err != nil {
121115
return err
122116
}
123117

124-
if height <= p.retention {
118+
if height <= retention {
125119
return nil
126120
}
127121

128-
target := height - p.retention
122+
target := height - retention
129123
if target <= p.lastPruned {
130124
return nil
131125
}
@@ -143,7 +137,7 @@ func (p *Pruner) pruneOnce(ctx context.Context) error {
143137
}
144138
}
145139
if p.execPruner != nil {
146-
if err := p.execPruner.PruneExecMeta(ctx, h); err != nil && !errors.Is(err, ds.ErrNotFound) {
140+
if err := p.execPruner.PruneExec(ctx, h); err != nil && !errors.Is(err, ds.ErrNotFound) {
147141
return err
148142
}
149143
}

block/internal/pruner/pruner_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package pruner
33
import (
44
"context"
55
"testing"
6-
"time"
76

87
ds "github.com/ipfs/go-datastore"
98
dssync "github.com/ipfs/go-datastore/sync"
109
"github.com/rs/zerolog"
1110
"github.com/stretchr/testify/require"
1211

12+
"github.com/evstack/ev-node/pkg/config"
1313
"github.com/evstack/ev-node/pkg/store"
1414
"github.com/evstack/ev-node/types"
1515
)
@@ -18,7 +18,7 @@ type execMetaAdapter struct {
1818
existing map[uint64]struct{}
1919
}
2020

21-
func (e *execMetaAdapter) PruneExecMeta(ctx context.Context, height uint64) error {
21+
func (e *execMetaAdapter) PruneExec(ctx context.Context, height uint64) error {
2222
delete(e.existing, height)
2323
return nil
2424
}
@@ -40,8 +40,8 @@ func TestPrunerPrunesRecoveryHistory(t *testing.T) {
4040

4141
execAdapter := &execMetaAdapter{existing: map[uint64]struct{}{1: {}, 2: {}, 3: {}}}
4242

43-
recoveryPruner := New(stateStore, execAdapter, 2, time.Minute, zerolog.Nop())
44-
require.NoError(t, recoveryPruner.pruneOnce(ctx))
43+
recoveryPruner := New(zerolog.Nop(), stateStore, execAdapter, config.NodeConfig{RecoveryHistoryDepth: 2})
44+
require.NoError(t, recoveryPruner.pruneRecoveryHistory(ctx, recoveryPruner.cfg.RecoveryHistoryDepth))
4545

4646
_, err := stateStore.GetStateAtHeight(ctx, 1)
4747
require.ErrorIs(t, err, ds.ErrNotFound)

pkg/store/store.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ func New(ds ds.Batching) Store {
3030
}
3131
}
3232

33-
// DeleteStateAtHeight removes the state entry at the given height.
34-
func (s *DefaultStore) DeleteStateAtHeight(ctx context.Context, height uint64) error {
35-
if err := s.db.Delete(ctx, ds.NewKey(getStateAtHeightKey(height))); err != nil && !errors.Is(err, ds.ErrNotFound) {
36-
return fmt.Errorf("failed to delete state at height %d: %w", height, err)
37-
}
38-
return nil
39-
}
40-
4133
// Close safely closes underlying data storage, to ensure that data is actually saved.
4234
func (s *DefaultStore) Close() error {
4335
return s.db.Close()
@@ -180,6 +172,14 @@ func (s *DefaultStore) GetStateAtHeight(ctx context.Context, height uint64) (typ
180172
return state, nil
181173
}
182174

175+
// DeleteStateAtHeight removes the state entry at the given height.
176+
func (s *DefaultStore) DeleteStateAtHeight(ctx context.Context, height uint64) error {
177+
if err := s.db.Delete(ctx, ds.NewKey(getStateAtHeightKey(height))); err != nil && !errors.Is(err, ds.ErrNotFound) {
178+
return fmt.Errorf("failed to delete state at height %d: %w", height, err)
179+
}
180+
return nil
181+
}
182+
183183
// SetMetadata saves arbitrary value in the store.
184184
//
185185
// Metadata is separated from other data by using prefix in KV.

0 commit comments

Comments
 (0)