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

refactor: snapshot and pruning functionality #140

Merged
merged 41 commits into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f348dc1
refactor snapshot config
p0mvn Mar 13, 2022
9b34767
create pruning package and move pruning options into it
p0mvn Mar 13, 2022
f45b027
introduce snapshot options struct, similar to pruning options
p0mvn Mar 13, 2022
1468df4
implement pruning manager and unit test
p0mvn Mar 15, 2022
8e37e0d
snapshot inteval must be equal to pruning keep recent
p0mvn Mar 15, 2022
8ad567e
multistore PruneHeight stub and unit test with mocks
p0mvn Mar 15, 2022
49b269c
implement the barebones logic for pruning keep-every after snapshot a…
p0mvn Mar 16, 2022
e6be907
rename multistore PruneHeight to PruneSnapshotHeight and implement it
p0mvn Mar 16, 2022
4a78172
add logs
p0mvn Mar 16, 2022
19831f8
fix unit tests
p0mvn Mar 16, 2022
fa53501
refactor baseapp_test.go
p0mvn Mar 16, 2022
de9c030
refactor pruning options.go
p0mvn Mar 16, 2022
4df3ffd
finalize TestSnapshotWithPruning and ensure all unit tests pass
p0mvn Mar 16, 2022
ed59a43
implement GetSnapshotBlockRetentionHeights
p0mvn Mar 16, 2022
02b4c03
add pruning types and constructors to sdk types package
p0mvn Mar 16, 2022
b658d9b
clean up pruning and snaphot error messages and names
p0mvn Mar 16, 2022
e318a90
remove dependency on pruning types from baseapp_test.go
p0mvn Mar 16, 2022
1a78b81
further clean up baseapp_test.go
p0mvn Mar 16, 2022
fff4055
improve comment in options.go
p0mvn Mar 16, 2022
4487e79
fix comment in pruning/manager.go
p0mvn Mar 16, 2022
6e70a75
remove junk file
p0mvn Mar 16, 2022
24478ee
remove pruning-keep-every and use snapshot-interval instead
p0mvn Mar 17, 2022
d0ceed6
remveo all references to pruning-keep-every
p0mvn Mar 17, 2022
8733ac7
allow snapshot-keep-recent of 0, add more unit tests
p0mvn Mar 17, 2022
0b62de4
bug fixes related to prune-everything
p0mvn Mar 17, 2022
9d34297
add unit tests for app.init(), remove validation from snapshot manage…
p0mvn Mar 17, 2022
835cf32
clean up
p0mvn Mar 17, 2022
157bb38
optimize deletion from list while iterating
p0mvn Mar 17, 2022
e8e94cf
golangci-lint run --fix
p0mvn Mar 17, 2022
183b8e6
Update store/types/store.go
p0mvn Mar 18, 2022
3775b3e
restore config tests
p0mvn Mar 18, 2022
db8661c
rename Type to PruningStrategy, prefix strategy names with "Pruning"
p0mvn Mar 18, 2022
3be7f3d
change Snapshot to SnapshotIfApplicable
p0mvn Mar 21, 2022
c9d827c
Update snapshots/manager.go
p0mvn Mar 21, 2022
197552f
change log level in SnapshotIfApplicable
p0mvn Mar 21, 2022
948387d
add comments for stores in snapshot manager
p0mvn Mar 21, 2022
4f48a83
check for snapshots enabled with non-multi store
p0mvn Mar 22, 2022
56b4781
add documentation in snapshots/README.md
p0mvn Mar 22, 2022
bdb1112
get latest version directly from the db in Snapshot() to avoid data race
p0mvn Mar 22, 2022
a619355
update documentation in pruning/README.md and snapshots/README.md
p0mvn Mar 22, 2022
bc941a0
update iavl to v6 with the data race fix
p0mvn Mar 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
finalize TestSnapshotWithPruning and ensure all unit tests pass
  • Loading branch information
p0mvn committed Mar 21, 2022
commit 4df3ffd33397d9d2187b3685e2b6d5b142750da4
17 changes: 9 additions & 8 deletions baseapp/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import (
"fmt"
"testing"

"github.com/cosmos/cosmos-sdk/snapshots"
pruningTypes "github.com/cosmos/cosmos-sdk/pruning/types"
snaphotsTestUtil "github.com/cosmos/cosmos-sdk/testutil/snapshots"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
tmprototypes "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/snapshots"
snaphotsTestUtil "github.com/cosmos/cosmos-sdk/testutil/snapshots"
sdk "github.com/cosmos/cosmos-sdk/types"
)

func TestGetBlockRentionHeight(t *testing.T) {
Expand Down Expand Up @@ -43,7 +44,7 @@ func TestGetBlockRentionHeight(t *testing.T) {
"pruning iavl snapshot only": {
bapp: NewBaseApp(
name, logger, db, nil,
SetPruning(sdk.NewCustomPruningOptions(0, 10000, 0)),
SetPruning(pruningTypes.NewCustomPruningOptions(0, 10000, 0)),
SetMinRetainBlocks(1),
),
maxAgeBlocks: 0,
Expand Down Expand Up @@ -72,7 +73,7 @@ func TestGetBlockRentionHeight(t *testing.T) {
"pruning all conditions": {
bapp: NewBaseApp(
name, logger, db, nil,
SetPruning(sdk.NewCustomPruningOptions(0, 10000, 0)),
SetPruning(pruningTypes.NewCustomPruningOptions(0, 10000, 0)),
SetMinRetainBlocks(400000),
SetSnapshot(snapshotStore, sdk.NewSnapshotOptions(50000, 3)),
),
Expand All @@ -83,7 +84,7 @@ func TestGetBlockRentionHeight(t *testing.T) {
"no pruning due to no persisted state": {
bapp: NewBaseApp(
name, logger, db, nil,
SetPruning(sdk.NewCustomPruningOptions(0, 10000, 0)),
SetPruning(pruningTypes.NewCustomPruningOptions(0, 10000, 0)),
SetMinRetainBlocks(400000),
SetSnapshot(snapshotStore, sdk.NewSnapshotOptions(50000, 3)),
),
Expand All @@ -94,7 +95,7 @@ func TestGetBlockRentionHeight(t *testing.T) {
"disable pruning": {
bapp: NewBaseApp(
name, logger, db, nil,
SetPruning(sdk.NewCustomPruningOptions(0, 10000, 0)),
SetPruning(pruningTypes.NewCustomPruningOptions(0, 10000, 0)),
SetMinRetainBlocks(0),
SetSnapshot(snapshotStore, sdk.NewSnapshotOptions(50000, 3)),
),
Expand Down
7 changes: 4 additions & 3 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,15 @@ func (app *BaseApp) init() error {
snapshotInterval := app.snapshotManager.GetInterval()

// pruning-keep-every must be enabled if snapshot is on
if pruningType != pruningTypes.Everything && snapshotInterval > 0 && pruningOpts.KeepEvery == 0 {
if snapshotInterval > 0 && pruningOpts.KeepEvery == 0 && pruningType == pruningTypes.Custom {
return errOptsZeroKeepRecentWithSnapshot(snapshotInterval)
}
// snapshot-interval must be enabled if pruning-keep-every is
if snapshotInterval == 0 && pruningOpts.KeepEvery > 0 {
return errOptsNonZeroKeepRecentWithZeroSnapshot(pruningOpts.KeepEvery)
}
// if strategy is not PruneNothing or PruneEverything, pruning-keep-every must be equal to snapshot-interval
if pruningType != pruningTypes.Nothing && pruningType != pruningTypes.Everything && snapshotInterval != pruningOpts.KeepEvery {
// if types is custom, pruning-keep-every must be equal to snapshot-interval
if snapshotInterval != pruningOpts.KeepEvery && pruningType == pruningTypes.Custom {
return errOptsNotEqualsPruningKeepRecentWithSnapshot(snapshotInterval, pruningOpts.KeepEvery)
}
} else {
Expand Down
189 changes: 97 additions & 92 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ func TestLoadVersionInvalid(t *testing.T) {

func TestLoadVersionPruning(t *testing.T) {
logger := log.NewNopLogger()
pruningOptions := sdk.NewCustomPruningOptions(2, 3, 1)
pruningOptions := pruningTypes.NewCustomPruningOptions(2, 3, 1)
pruningOpt := SetPruning(pruningOptions)
db := dbm.NewMemDB()
name := t.Name()
Expand Down Expand Up @@ -1839,92 +1839,91 @@ func TestListSnapshots(t *testing.T) {
}}, resp)
}

func TestSnapshotWithPruning_CustomPruning(t *testing.T) {
func TestSnapshotWithPruning(t *testing.T) {
testcases := map[string]struct {
config *setupConfig
expectedSnapshots []*abci.Snapshot
expectedErr error
} {
// "error pruning-keep-every and snapshot-interval mismatch": {
// config: &setupConfig{
// blocks: 0,
// blockTxs: 0,
// snapshotInterval: 1,
// snapshotKeepEvery: 2,
// pruningOpts: sdk.NewPruningOptions(1, 5, 1),
// },
// expectedErr: errOptsNotEqualsPruningKeepRecentWithSnapshot(1, 5),
// },
// "error pruning-keep-every is non-zero when snapshot-interval is": {
// config: &setupConfig{
// blocks: 0,
// blockTxs: 0,
// snapshotInterval: 0,
// snapshotKeepEvery: 0,
// pruningOpts: sdk.NewPruningOptions(1, 1, 1),
// },
// expectedErr: errOptsNonZeroKeepRecentWithZeroSnapshot(1),
// },
// "error pruning-keep-every does not equal snapshot-interval": {
// config: &setupConfig{
// blocks: 0,
// blockTxs: 0,
// snapshotInterval: 5,
// snapshotKeepEvery: 1,
// pruningOpts: sdk.NewPruningOptions(1, 4, 1),
// },
// expectedErr: errOptsNotEqualsPruningKeepRecentWithSnapshot(5, 4),
// },
// "prune nothing with snapshot": {
// config: &setupConfig{
// blocks: 20,
// blockTxs: 2,
// snapshotInterval: 5,
// snapshotKeepEvery: 1,
// pruningOpts: sdk.PruneNothing,
// },
// expectedSnapshots: []*abci.Snapshot{
// {Height: 20, Format: 1, Chunks: 5},
// },
// },
// "prune everything with snapshot": {
// config: &setupConfig{
// blocks: 20,
// blockTxs: 2,
// snapshotInterval: 5,
// snapshotKeepEvery: 1,
// pruningOpts: sdk.PruneEverything,
// },
// expectedSnapshots: []*abci.Snapshot{
// {Height: 20, Format: 1, Chunks: 5},
// },
// },

// "default pruning with snapshot": {
// config: &setupConfig{
// blocks: 20,
// blockTxs: 2,
// snapshotInterval: 5,
// snapshotKeepEvery: 1,
// pruningOpts: pruningTypes.NewPruningOptions(pruningTypes.Default),
// },
// expectedSnapshots: []*abci.Snapshot{
// {Height: 20, Format: 1, Chunks: 5},
// },
// },
// "custom": {
// config: &setupConfig{
// blocks: 20,
// blockTxs: 2,
// snapshotInterval: 5,
// snapshotKeepEvery: 2,
// pruningOpts: sdk.NewPruningOptions(10, 5, 3),
// },
// expectedSnapshots: []*abci.Snapshot{
// {Height: 20, Format: 1, Chunks: 5},
// {Height: 15, Format: 1, Chunks: 4},
// },
// },
"error pruning-keep-every and snapshot-interval mismatch": {
config: &setupConfig{
blocks: 0,
blockTxs: 0,
snapshotInterval: 1,
snapshotKeepEvery: 2,
pruningOpts: pruningTypes.NewCustomPruningOptions(1, 5, 1),
},
expectedErr: errOptsNotEqualsPruningKeepRecentWithSnapshot(1, 5),
},
"error pruning-keep-every is non-zero when snapshot-interval is": {
config: &setupConfig{
blocks: 0,
blockTxs: 0,
snapshotInterval: 0,
snapshotKeepEvery: 0,
pruningOpts: pruningTypes.NewCustomPruningOptions(1, 1, 1),
},
expectedErr: errOptsNonZeroKeepRecentWithZeroSnapshot(1),
},
"error pruning-keep-every does not equal snapshot-interval": {
config: &setupConfig{
blocks: 0,
blockTxs: 0,
snapshotInterval: 5,
snapshotKeepEvery: 1,
pruningOpts: pruningTypes.NewCustomPruningOptions(1, 4, 1),
},
expectedErr: errOptsNotEqualsPruningKeepRecentWithSnapshot(5, 4),
},
"prune nothing with snapshot": {
config: &setupConfig{
blocks: 20,
blockTxs: 2,
snapshotInterval: 5,
snapshotKeepEvery: 1,
pruningOpts: pruningTypes.NewPruningOptions(pruningTypes.Nothing),
},
expectedSnapshots: []*abci.Snapshot{
{Height: 20, Format: 1, Chunks: 5},
},
},
"prune everything with snapshot": {
config: &setupConfig{
blocks: 20,
blockTxs: 2,
snapshotInterval: 5,
snapshotKeepEvery: 1,
pruningOpts: pruningTypes.NewPruningOptions(pruningTypes.Everything),
},
expectedSnapshots: []*abci.Snapshot{
{Height: 20, Format: 1, Chunks: 5},
},
},
"default pruning with snapshot": {
config: &setupConfig{
blocks: 20,
blockTxs: 2,
snapshotInterval: 5,
snapshotKeepEvery: 1,
pruningOpts: pruningTypes.NewPruningOptions(pruningTypes.Default),
},
expectedSnapshots: []*abci.Snapshot{
{Height: 20, Format: 1, Chunks: 5},
},
},
"custom": {
config: &setupConfig{
blocks: 20,
blockTxs: 2,
snapshotInterval: 5,
snapshotKeepEvery: 2,
pruningOpts: pruningTypes.NewCustomPruningOptions(10, 5, 3),
},
expectedSnapshots: []*abci.Snapshot{
{Height: 20, Format: 1, Chunks: 5},
{Height: 15, Format: 1, Chunks: 4},
},
},
}

for name, tc := range testcases {
Expand All @@ -1950,30 +1949,36 @@ func TestSnapshotWithPruning_CustomPruning(t *testing.T) {
fmt.Println(resp)
assert.Equal(t, abci.ResponseListSnapshots{Snapshots: tc.expectedSnapshots}, resp)

// validate that heights were pruned correctly
// Validate that heights were pruned correctly by querying the state at the last height from that should be present relative to latest
// and the first height that should be pruned.
//
// Exceptions:
// * Prune everything: should only be able to query latest height
// * Prune nothing: should be able to query all heights (we only test first and latest)
// * Prunde default: should be able to query all heights (we only test first and latest)
// * The reason for default behaving this way is that we only commit 20 heights but default has 100_000 keep-recent
var lastExistingHeight int64
if tc.config.pruningOpts.GetType() == pruningTypes.Nothing {
lastExistingHeight = 1
} else if tc.config.pruningOpts.GetType() == pruningTypes.Everything {
} else if tc.config.pruningOpts.GetType() == pruningTypes.Everything || tc.config.pruningOpts.GetType() == pruningTypes.Default {
lastExistingHeight = int64(tc.config.blocks)
} else {
// Integer division rounds down so by multiplying back we get the last height at which we prune
// Integer division rounds down so by multiplying back we get the last height at which we pruned
lastExistingHeight = int64((tc.config.blocks / tc.config.pruningOpts.Interval) * tc.config.pruningOpts.Interval - tc.config.pruningOpts.KeepRecent)
}

res := app.Query(abci.RequestQuery{Path: fmt.Sprintf("/store/%s/key", capKey2.Name()), Data: []byte("0"), Height: lastExistingHeight})
require.NotNil(t, res)
require.NotNil(t, res.Value)
require.NotNil(t, res, "height: %d", lastExistingHeight)
require.NotNil(t, res.Value, "height: %d", lastExistingHeight)

res = app.Query(abci.RequestQuery{Path: fmt.Sprintf("/store/%s/key", capKey2.Name()), Data: []byte("0"), Height: lastExistingHeight - 1})
require.NotNil(t, res)
if tc.config.pruningOpts.GetType() == pruningTypes.Nothing {
require.NotNil(t, res, "height: %d", lastExistingHeight - 1)
if tc.config.pruningOpts.GetType() == pruningTypes.Nothing || tc.config.pruningOpts.GetType() == pruningTypes.Default {
// With prune nothing, we query height 0 which translates to the latest height.
require.NotNil(t, res)
require.NotNil(t, res.Value)
require.NotNil(t, res.Value, "height: %d", lastExistingHeight - 1)
} else {
require.Nil(t, res.Value)
require.Equal(t, iavl.ErrVersionDoesNotExist.Error(), res.Log)
require.Equal(t, iavl.ErrVersionDoesNotExist.Error(), res.Log, "height: %d", lastExistingHeight - 1)
}
})
}
Expand Down
4 changes: 0 additions & 4 deletions types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,3 @@ func NewInfiniteGasMeter() GasMeter {
func NewSnapshotOptions(interval uint64, keepRecent uint32) *snapshotTypes.SnapshotOptions {
return snapshotTypes.NewSnapshotOptions(interval, keepRecent)
}

func NewCustomPruningOptions(keepRecent, keepEvery, interval uint64) *pruningTypes.PruningOptions {
return pruningTypes.NewCustomPruningOptions(keepRecent, keepEvery, interval)
}