Conversation
|
@greptileai please review this PR |
Greptile SummaryThis PR completes the transition from BadgerDB to PebbleDB for all SSV node operators (not just exporter), removing the entire Badger storage implementation from the main module and replacing it with a unified Pebble backend. Key changes:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Node Startup] --> B[ResolvePebbleDBPlan basePath]
B --> C{Canonical Pebble\nnon-empty AND\nno legacy Pebble?}
C -->|Yes| D{Import marker\nexists at basePath?}
D -->|Yes - fast path| E[Plan: PebblePath=basePath\nBadgerImportPath=basePath]
C -->|No| F{Legacy Pebble\nnon-empty AND\nno canonical Pebble?}
F -->|Yes| G{Import marker\nexists at legacyPath?}
G -->|Yes - fast path| H[Plan: PebblePath=legacyPebblePath\nBadgerImportPath=basePath]
F -->|No| I[Call badgerDirState]
D -->|No| I
G -->|No| I
I --> J{Multiple non-empty\nDBs detected?}
J -->|Yes + marker| K[Resolve with marker]
J -->|Yes no marker| L[Fatal: ambiguous state]
J -->|No| M{Which DB\nhas data?}
M -->|canonical Pebble| N[Plan: PebblePath=basePath]
M -->|legacy Pebble| O[Plan: PebblePath=legacyPebblePath]
M -->|Badger only| P[Plan: PebblePath=legacyPebblePath\nBadgerImportPath=basePath]
M -->|None| Q[Plan: PebblePath=basePath fresh]
E --> R[Open Pebble DB]
H --> R
N --> R
O --> R
P --> R
Q --> R
K --> R
R --> S{BadgerImportPath set?}
S -->|No| X[Apply SSV Migrations]
S -->|Yes| T[MigrateBadgerToPebbleIfNeeded]
T --> U{Done marker\nexists?}
U -->|Yes + Pebble not empty| X
U -->|No| V{Pebble empty\nor in-progress marker?}
V -->|Resume| W[copyBadgerToPebble\nwith context checks\nevery key]
V -->|Both non-empty\nno markers| L2[Fatal: partial migration]
W --> Y[Write done marker\nRemove in-progress marker]
Y --> X
X --> Z[Node Running]
|
Codecov Report❌ Patch coverage is ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@greptileai please review it again |
|
@greptileai review it again |
Additional Comments (2)
If
If |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR. Don't limit the number of comments to 3 — post all the comments you have |
|
@greptileai review this again, considering all comments on this PR |
|
@greptileai review this again, considering all comments on this PR |
| hasBadgerData, badgerNonEmpty, err = badgerDirState(badgerPath) | ||
| if err != nil { | ||
| return false, 0, err | ||
| } | ||
| } | ||
|
|
||
| if !pebbleEmpty { |
There was a problem hiding this comment.
hasBadgerData and badgerNonEmpty conflated to same boolean when state is known
When badgerStateKnown=true, both hasBadgerData (semantically "Badger directory has files") and badgerNonEmpty (semantically "Badger DB has at least one key") are assigned the same value knownBadgerNonEmpty. This conflates two distinct states: a Badger directory can exist and be empty (hasBadgerData=true, badgerNonEmpty=false), but with badgerStateKnown=true and knownBadgerNonEmpty=false, both become false.
As a result, when badgerStateKnown=true and the Badger DB is empty (but files exist), the function exits via if !hasBadgerData { return false, 0, nil } silently, instead of via the if !badgerNonEmpty { logger.Info("legacy badger database is empty...") } path. The "skipping import because empty" log line is never emitted in this case.
While this is currently harmless because ResolvePebbleDBPlan only sets BadgerImportPath when badgerNonEmpty=true, MigrateBadgerToPebbleIfNeeded is an exported function and callers providing badgerStateKnown=true, badgerNonEmpty=false when Badger files genuinely exist will silently skip migration without any diagnostic log.
Consider using two distinct fields in PebbleDBPlan or a dedicated PebbleDBPlan.BadgerExists bool to preserve the semantic distinction, or document that BadgerNonEmpty=false implies "no Badger files or empty Badger".
| db2, err := kv.New(logger, basedb.Options{Path: dbPath}) | ||
| db2, err := pebble.New(logger, dbPath, nil) | ||
| require.NoError(t, err) | ||
| defer db2.Close() |
There was a problem hiding this comment.
defer db2.Close() error unchecked in Phase 2
defer db2.Close() discards the close error. If the pebble DB fails to flush or sync on close, the test will pass silently despite a DB error. For consistency with how db.Close() is handled in Phase 1 (line 945–946 with require.NoError), prefer using t.Cleanup:
| defer db2.Close() | |
| t.Cleanup(func() { require.NoError(t, db2.Close()) }) |
The PR applies Pebble DB usage for both ssv-node and exporter instead of Badger DB for ssv-node and Pebble DB for exporter.