Release oasis storage prune and compact subcomands - #6521
Conversation
✅ Deploy Preview for oasisprotocol-oasis-core canceled.
|
c39199f to
ddd1106
Compare
| // By calculating retain round from the runtime state DB latest round, | ||
| // we ensure light history is never pruned past the latest synced runtime | ||
| // round. | ||
| retainRound := latest - numKept |
There was a problem hiding this comment.
In practice we should probably also respect executor prune handler that should prevent pruning past last normal round.
// runtimeLastNormalRound returns the last normal round for the given runtime.
func runtimeLastNormalRound(ctx context.Context, ndb db.NodeDB, runtimeID common.Namespace) (uint64, error) {
latest, ok := ndb.GetLatestVersion()
if !ok {
return 0, fmt.Errorf("consensus node DB is empty")
}
roots, err := ndb.GetRootsForVersion(latest)
if err != nil {
return 0, fmt.Errorf("failed to get roots for consensus version %d: %w", latest, err)
}
if len(roots) == 0 {
return 0, fmt.Errorf("no roots found for consensus version %d", latest)
}
tree := mkvs.NewWithRoot(nil, ndb, roots[0], mkvs.WithoutWriteLog())
defer tree.Close()
s := roothashState.NewImmutableState(tree)
rtState, err := s.RuntimeState(ctx, runtimeID)
if err != nil {
return 0, fmt.Errorf("failed to get runtime state: %w", err)
}
return rtState.LastNormalRound, nil
}We have two options:
- Pass consensus node DB to
pruneRuntimeDBs.- Or just open and close it there (simplest and least changes).
- This feels weird as this function should probably accept
retainRound, likepruneConsensusDBsshould acceptretainHeightinstead ofruntimeIds(solution 2.).
- Add new
consensusRetainHeightandruntimeRetainRoundfunctions that precompute this limits, possibly write unit tests for those two functions. The annoying part is that those two functions consume runtime histories, nodedbs and consensus nodedbs, meaning we loose resource encapsulation and need to keep them open throughout the whole command. Feels like a better direction, but requires a thorough refactor + makes logging and orchestration incredibly messy.
In addition adding this handler requires consensus state to be always present. Without it you can prune runtime state without having a consensus state locally (e.g. when hacking state if imported using snapshots, don't think this is needed though).
There was a problem hiding this comment.
We can also hardcode sain default e.g. min few days retention, and leave a TODO issue.
| ndb, close, err := openConsensusNodeDB(dataDir) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to open NodeDB: %w", err) | ||
| } | ||
| defer close() | ||
|
|
||
| latest, ok := ndb.GetLatestVersion() | ||
| if !ok { | ||
| logger.Info("skipping consensus pruning as state db is empty") | ||
| return nil | ||
| } | ||
|
|
||
| if latest < numKept { | ||
| logger.Info("skipping consensus pruning as the latest version is smaller than the number of versions to keep") | ||
| return nil | ||
| } | ||
|
|
||
| // In case of configured runtimes, do not prune past the earliest reindexed | ||
| // consensus height, so that light history can be populated correctly. | ||
| minReindexed, err := minReindexedHeight(dataDir, runtimes) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to fetch earliest reindexed consensus height: %w", err) | ||
| } | ||
|
|
||
| retainHeight := min( | ||
| latest-numKept, // underflow not possible due to if above. | ||
| uint64(minReindexed), | ||
| ) |
There was a problem hiding this comment.
E.g. this could be func consensusRetainHeight(ndb db.NodeDB, histories []history.Histories)(uint64, bool, error) and this function takes retainHeight: uint64 instead of the last two params, which would also allow us to unit test the business logic. As stated above this complicates the orchestration a lot though :(
ddd1106 to
c768a9a
Compare
| logger.Info("Starting databases pruning. This may take a while...") | ||
|
|
||
| dataDir := cmdCommon.DataDir() | ||
| ctx := cmd.Context() |
There was a problem hiding this comment.
NIT: We should probably wire
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) .As cobra context does not capture this signals by default, resulting in non-graceful shutdown (never had an issue so fat though). Still it is annoying that BadgerDB command does not expose cancelation api, so even with this fixed it won't be complete.
c768a9a to
32bbd4e
Compare
|
Ready for a review. Please check the PR context, the main question is how much do we want to complicate our life with prune handlers - comment. Since the PR is already rather big, I am open to push one PR infront that does:
Then this PR becomes much smaller and focused only one new runtime logic and releasing the commands. |
833255a to
0c40ffa
Compare
0c40ffa to
e5b4a63
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #6521 +/- ##
==========================================
- Coverage 64.12% 64.09% -0.04%
==========================================
Files 698 700 +2
Lines 68253 68416 +163
==========================================
+ Hits 43770 43854 +84
+ Misses 19556 19506 -50
- Partials 4927 5056 +129 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
58b29c5 to
4b52f99
Compare
Align the style with storage inspect command. This is prefered as the scope of the commands variables is reduced, and enables testing of the cobra command directly.
Best way to mitigate unlikely stale state scenario. Moreover, it enables introducing context cancelation.
Offline compaction now also works for the runtime history and state DB.
Make it symetric with the prune command helpers.
4b52f99 to
d3189ce
Compare
Closes #6519.
Relatively trivial to review. LOC is big because I extracted commands to separate files and added missing tests (separate commits).
Motivation
How to test locally
For testing I used latest Sapphire snapshot (cca 7 months of data,
keep_n = 100_000). It took 10min to prune and 6min to compact. For consensus I used snapshot-old (cca 3 months of data,keep_n = 100_000), due to limited disk space on my machine. Pruning took 2min and compaction 3min.Node started syncing normally after prune/compact commands.
Possible follow-up
For #6454, we may want to add additional flag to the pruning command, e.g.
retain_height, that ignores pruning config and calculates corresponding rounds at this height of every runtime, implementingkeep_fromproposal.