Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

control status: Show current history reindex round number #5998

Open
matevz opened this issue Jan 13, 2025 · 0 comments · May be fixed by #6013
Open

control status: Show current history reindex round number #5998

matevz opened this issue Jan 13, 2025 · 0 comments · May be fixed by #6013
Assignees

Comments

@matevz
Copy link
Member

matevz commented Jan 13, 2025

SUMMARY

Show the progress of the history reindex in oasis control status.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

go/control,

func (sc *serviceClient) reindexBlocks(currentHeight int64, bh api.BlockHistory) (uint64, error) {
lastRound := api.RoundInvalid
if currentHeight <= 0 {
return lastRound, nil
}
runtimeID := bh.RuntimeID()
logger := sc.logger.With("runtime_id", runtimeID)
var err error
var lastHeight int64
if lastHeight, err = bh.LastConsensusHeight(); err != nil {
sc.logger.Error("failed to get last indexed height",
"err", err,
)
return lastRound, fmt.Errorf("failed to get last indexed height: %w", err)
}
// +1 since we want the last non-seen height.
lastHeight++
// Take prune strategy into account.
lastRetainedHeight, err := sc.backend.GetLastRetainedVersion(sc.ctx)
if err != nil {
return lastRound, fmt.Errorf("failed to get last retained height: %w", err)
}
if lastHeight < lastRetainedHeight {
logger.Debug("last height pruned, skipping until last retained",
"last_retained_height", lastRetainedHeight,
"last_height", lastHeight,
)
lastHeight = lastRetainedHeight
}
// Take initial genesis height into account.
genesisDoc, err := sc.backend.GetGenesisDocument(sc.ctx)
if err != nil {
return lastRound, fmt.Errorf("failed to get genesis document: %w", err)
}
if lastHeight < genesisDoc.Height {
lastHeight = genesisDoc.Height
}
// Scan all blocks between last indexed height and current height.
logger.Debug("reindexing blocks",
"last_indexed_height", lastHeight,
"current_height", currentHeight,
logging.LogEvent, api.LogEventHistoryReindexing,
)
for height := lastHeight; height <= currentHeight; height++ {
var results *cmtrpctypes.ResultBlockResults
results, err = sc.backend.GetBlockResults(sc.ctx, height)
if err != nil {
// XXX: could soft-fail first few heights in case more heights were
// pruned right after the GetLastRetainedVersion query.
logger.Error("failed to get cometbft block results",
"err", err,
"height", height,
)
return lastRound, fmt.Errorf("failed to get cometbft block results: %w", err)
}
// Index block.
tmEvents := results.BeginBlockEvents
for _, txResults := range results.TxsResults {
tmEvents = append(tmEvents, txResults.Events...)
}
tmEvents = append(tmEvents, results.EndBlockEvents...)
for _, tmEv := range tmEvents {
if tmEv.GetType() != app.EventType {
continue
}
var evRtID *common.Namespace
var ev *api.FinalizedEvent
for _, pair := range tmEv.GetAttributes() {
key := pair.GetKey()
val := pair.GetValue()
switch {
case eventsAPI.IsAttributeKind(key, &api.RuntimeIDAttribute{}):
if evRtID != nil {
return 0, fmt.Errorf("roothash: duplicate runtime ID attribute")
}
var rtAttribute api.RuntimeIDAttribute
if err = eventsAPI.DecodeValue(val, &rtAttribute); err != nil {
return 0, fmt.Errorf("roothash: corrupt runtime ID: %w", err)
}
evRtID = &rtAttribute.ID
case eventsAPI.IsAttributeKind(key, &api.FinalizedEvent{}):
var e api.FinalizedEvent
if err = eventsAPI.DecodeValue(val, &e); err != nil {
logger.Error("failed to unmarshal finalized event",
"err", err,
"height", height,
)
return 0, fmt.Errorf("failed to unmarshal finalized event: %w", err)
}
ev = &e
default:
}
}
// Only process finalized events.
if ev == nil {
continue
}
// Only process events for the given runtime.
if !evRtID.Equal(&runtimeID) {
continue
}
if err = sc.processFinalizedEvent(sc.ctx, height, *evRtID, &ev.Round, true); err != nil {
return 0, fmt.Errorf("failed to process finalized event: %w", err)
}
lastRound = ev.Round
}
}
if lastRound == api.RoundInvalid {
sc.logger.Debug("no new round reindexed, return latest known round")
switch blk, err := bh.GetCommittedBlock(sc.ctx, api.RoundLatest); err {
case api.ErrNotFound:
case nil:
lastRound = blk.Header.Round
default:
return lastRound, fmt.Errorf("failed to get latest block: %w", err)
}
}
sc.logger.Debug("block reindex complete",
"last_round", lastRound,
)
return lastRound, nil
}

ADDITIONAL INFORMATION

Related to #5738 it would be useful for oasis-node to report the current reindex round so that the node operator could estimate when the reindex will finish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants