-
Notifications
You must be signed in to change notification settings - Fork 83
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
fix(manager/indexer): pruning fixes #1147
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still in the middle of the review
block/pruning.go
Outdated
// PruneBlocks prune all block related data from dymint store up to (but not including) retainHeight. It returns the number of blocks pruned, used for testing. | ||
func (m *Manager) PruneBlocks(retainHeight uint64) (uint64, error) { | ||
// PruneBlocks prune all block related data from dymint store up to (but not including) retainHeight. | ||
func (m *Manager) PruneBlocks(retainHeight uint64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you can DRY it out and remove the else
part also. check this (didn't test it):
func (m *Manager) PruneBlocks(retainHeight uint64) {
nextSubmissionHeight := m.NextHeightToSubmit()
if m.IsProposer() && nextSubmissionHeight < retainHeight {
m.logger.Debug("cannot prune blocks before they have been submitted. using height last submitted height for pruning", "retain_height", retainHeight, "height_to_submit", nextSubmissionHeight)
retainHeight = nextSubmissionHeight
}
m.pruneStore("blocksync", func(from, to uint64) (uint64, error) {
return m.P2PClient.RemoveBlocks(context.Background(), from, to)
}, &m.State.BaseBlocksyncHeight, retainHeight)
m.pruneStore("indexer", m.IndexerService.Prune, &m.State.BaseIndexerHeight, retainHeight)
m.pruneStore("dymint", func(from, to uint64) (uint64, error) {
return m.Store.PruneStore(from, to, m.logger)
}, &m.State.BaseHeight, retainHeight)
if _, err := m.Store.SaveState(m.State, nil); err != nil {
m.logger.Error("save state", "err", err)
}
}
func (m *Manager) pruneStore(storeName string, pruneFunc func(uint64, uint64) (uint64, error), baseHeight *uint64, retainHeight uint64) {
pruned, err := pruneFunc(*baseHeight, retainHeight)
if err != nil {
m.logger.Error(fmt.Sprintf("pruning %s store", storeName), "retain_height", retainHeight, "err", err)
return
}
m.logger.Debug(fmt.Sprintf("%s store pruned", storeName), "from", *baseHeight, "to", retainHeight, "pruned", pruned)
*baseHeight = retainHeight
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added inline func for logging
block/pruning.go
Outdated
} | ||
|
||
m.State.BaseHeight = retainHeight | ||
// store state with base heights updates | ||
_, err = m.Store.SaveState(m.State, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think saving the state in the background could lead on a race condition on the state as you may save incomplete state which was changed by the applyBlock.
The m.State
should only be ever accessed in either thread-safe way or by the applyBlock
.
I see no reason to save pruning data on the state but on an ad-hoc object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
baseheight moved to store outside state
indexers/txindex/kv/kv.go
Outdated
pruned := uint64(0) | ||
tobeFlushed := uint64(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tobe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
// first all events are pruned associated to the same height | ||
prunedEvents, err := txi.pruneEvents(h, batch) | ||
if err != nil { | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we log here at least something so will know we had problem pruning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
691f18a
to
e6d28c7
Compare
build n test failing sir |
a27927b
to
75e0ffe
Compare
block/manager.go
Outdated
@@ -101,6 +101,9 @@ type Manager struct { | |||
|
|||
// validates all non-finalized state updates from settlement, checking there is consistency between DA and P2P blocks, and the information in the state update. | |||
SettlementValidator *SettlementValidator | |||
|
|||
// BaseHeight is the height of the first block we have in store after pruning. | |||
BaseHeight uint64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
store/pruning.go
Outdated
} | ||
|
||
prunedBlocks, err := s.pruneBlocks(from, to, logger) | ||
prunedBlocks, err = s.pruneBlocks(from, to, logger) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we e.g get erorr here, than we still save the to
as base height. (i.e some stores succeeded and some not).
not sure if critical for now but probably worth opening an issue on it otherwise you have stores which are partially pruned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i actually refactored the func to prune all indexes for every height iteration, so in case it fails it will be more likely all failed at the same height, although the solution not perfect. i created issue for this #1196
@@ -325,8 +325,12 @@ func (c *Client) GenesisChunked(context context.Context, id uint) (*ctypes.Resul | |||
func (c *Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { | |||
const limit int64 = 20 | |||
|
|||
minHeight, maxHeight, err := filterMinMax( | |||
int64(c.node.BlockManager.State.BaseHeight), | |||
baseHeight, err := c.node.BlockManager.Store.LoadBaseHeight() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently we only set base height when pruning. it means if we never set pruning, will never have base height and we won't be able to serve this method.
when was base height saved before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set to 1 in case baseheight not found
_, err := is.blockIdxr.Prune(from, to, is.Logger) | ||
func (is *IndexerService) Prune(to uint64, s store.Store) (uint64, error) { | ||
// load indexer base height | ||
indexerBaseHeight, err := s.LoadIndexerBaseHeight() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems that if we fail to loa the height we just log it and the indexerBaseHeight
will be set to 0.
this means tha the pruning functions will be called with from
0 (e.g blockIndexer) (and may unncessarily iterate tons of indexes.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what is the issue here, if not found it means it was never set and therefore it needs to start from 0 because it was never pruned...
|
||
if to <= from { | ||
return fmt.Errorf("to height must be greater than from height: to: %d: from: %d: %w", to, from, gerrc.ErrInvalidArgument) | ||
from, err := c.store.LoadBlockSyncBaseHeight() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as my previous. from will be set to 0
which will cause very high iteration.
e92551b
to
9f47fed
Compare
2510be5
to
4ee4cfb
Compare
PR Standards
Opening a pull request should be able to meet the following requirements
--
PR naming convention: https://hackmd.io/@nZpxHZ0CT7O5ngTp0TP9mg/HJP_jrm7A
Close #1145
<-- Briefly describe the content of this pull request -->
For Author:
godoc
commentsFor Reviewer:
After reviewer approval: