Merge PR #5709: Add granularity options to pruning state

This commit is contained in:
Alexander Bezobchuk 2020-02-28 13:45:59 -08:00 committed by GitHub
commit 7d6fc7ee25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 233 additions and 11 deletions

View File

@ -148,6 +148,8 @@ Buffers for state serialization instead of Amino.
* (rest) [\#5648](https://github.com/cosmos/cosmos-sdk/pull/5648) Enhance /txs usability: * (rest) [\#5648](https://github.com/cosmos/cosmos-sdk/pull/5648) Enhance /txs usability:
* Add `tx.minheight` key to filter transaction with an inclusive minimum block height * Add `tx.minheight` key to filter transaction with an inclusive minimum block height
* Add `tx.maxheight` key to filter transaction with an inclusive maximum block height * Add `tx.maxheight` key to filter transaction with an inclusive maximum block height
* (server) [\#5709](https://github.com/cosmos/cosmos-sdk/pull/5709) There are two new flags for pruning, `--pruning-keep-every`
and `--pruning-snapshot-every` as an alternative to `--pruning`. They allow to fine tune the strategy for pruning the state.
## [v0.38.1] - 2020-02-11 ## [v0.38.1] - 2020-02-11

24
server/pruning.go Normal file
View File

@ -0,0 +1,24 @@
package server
import (
"github.com/cosmos/cosmos-sdk/store"
"github.com/spf13/viper"
)
// GetPruningOptionsFromFlags parses start command flags and returns the correct PruningOptions.
// flagPruning prevails over flagPruningKeepEvery and flagPruningSnapshotEvery.
// Default option is PruneSyncable.
func GetPruningOptionsFromFlags() store.PruningOptions {
if viper.IsSet(flagPruning) {
return store.NewPruningOptionsFromString(viper.GetString(flagPruning))
}
if viper.IsSet(flagPruningKeepEvery) && viper.IsSet(flagPruningSnapshotEvery) {
return store.PruningOptions{
KeepEvery: viper.GetInt64(flagPruningKeepEvery),
SnapshotEvery: viper.GetInt64(flagPruningSnapshotEvery),
}
}
return store.PruneSyncable
}

51
server/pruning_test.go Normal file
View File

@ -0,0 +1,51 @@
package server
import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/store"
)
func TestGetPruningOptionsFromFlags(t *testing.T) {
tests := []struct {
name string
initParams func()
expectedOptions store.PruningOptions
}{
{
name: "pruning",
initParams: func() {
viper.Set(flagPruning, store.PruningStrategyNothing)
},
expectedOptions: store.PruneNothing,
},
{
name: "granular pruning",
initParams: func() {
viper.Set(flagPruningSnapshotEvery, 1234)
viper.Set(flagPruningKeepEvery, 4321)
},
expectedOptions: store.PruningOptions{
SnapshotEvery: 1234,
KeepEvery: 4321,
},
},
{
name: "default",
initParams: func() {},
expectedOptions: store.PruneSyncable,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(j *testing.T) {
viper.Reset()
tt.initParams()
require.Equal(t, tt.expectedOptions, GetPruningOptionsFromFlags())
})
}
}

View File

@ -20,16 +20,29 @@ import (
// Tendermint full-node start flags // Tendermint full-node start flags
const ( const (
flagWithTendermint = "with-tendermint" flagWithTendermint = "with-tendermint"
flagAddress = "address" flagAddress = "address"
flagTraceStore = "trace-store" flagTraceStore = "trace-store"
flagPruning = "pruning" flagPruning = "pruning"
flagCPUProfile = "cpu-profile" flagPruningKeepEvery = "pruning-keep-every"
FlagMinGasPrices = "minimum-gas-prices" flagPruningSnapshotEvery = "pruning-snapshot-every"
FlagHaltHeight = "halt-height" flagCPUProfile = "cpu-profile"
FlagHaltTime = "halt-time" FlagMinGasPrices = "minimum-gas-prices"
FlagInterBlockCache = "inter-block-cache" FlagHaltHeight = "halt-height"
FlagUnsafeSkipUpgrades = "unsafe-skip-upgrades" FlagHaltTime = "halt-time"
FlagInterBlockCache = "inter-block-cache"
FlagUnsafeSkipUpgrades = "unsafe-skip-upgrades"
)
var (
errPruningWithGranularOptions = fmt.Errorf(
"'--%s' flag is not compatible with granular options '--%s' or '--%s'",
flagPruning, flagPruningKeepEvery, flagPruningSnapshotEvery,
)
errPruningGranularOptions = fmt.Errorf(
"'--%s' and '--%s' must be set together",
flagPruningSnapshotEvery, flagPruningKeepEvery,
)
) )
// StartCmd runs the service passed in, either stand-alone or in-process with // StartCmd runs the service passed in, either stand-alone or in-process with
@ -41,7 +54,9 @@ func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command {
Long: `Run the full node application with Tendermint in or out of process. By Long: `Run the full node application with Tendermint in or out of process. By
default, the application will run with Tendermint in process. default, the application will run with Tendermint in process.
Pruning options can be provided via the '--pruning' flag. The options are as follows: Pruning options can be provided via the '--pruning' flag or alternatively with '--pruning-snapshot-every' and 'pruning-keep-every' together.
For '--pruning' the options are as follows:
syncable: only those states not needed for state syncing will be deleted (flushes every 100th to disk and keeps every 10000th) syncable: only those states not needed for state syncing will be deleted (flushes every 100th to disk and keeps every 10000th)
nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node) nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
@ -56,6 +71,9 @@ will not be able to commit subsequent blocks.
For profiling and benchmarking purposes, CPU profiling can be enabled via the '--cpu-profile' flag For profiling and benchmarking purposes, CPU profiling can be enabled via the '--cpu-profile' flag
which accepts a path for the resulting pprof file. which accepts a path for the resulting pprof file.
`, `,
PreRunE: func(cmd *cobra.Command, args []string) error {
return checkPruningParams()
},
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
if !viper.GetBool(flagWithTendermint) { if !viper.GetBool(flagWithTendermint) {
ctx.Logger.Info("starting ABCI without Tendermint") ctx.Logger.Info("starting ABCI without Tendermint")
@ -74,6 +92,8 @@ which accepts a path for the resulting pprof file.
cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address") cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address")
cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file") cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file")
cmd.Flags().String(flagPruning, "syncable", "Pruning strategy: syncable, nothing, everything") cmd.Flags().String(flagPruning, "syncable", "Pruning strategy: syncable, nothing, everything")
cmd.Flags().Int64(flagPruningKeepEvery, 0, "Define the state number that will be kept")
cmd.Flags().Int64(flagPruningSnapshotEvery, 0, "Defines the state that will be snapshot for pruning")
cmd.Flags().String( cmd.Flags().String(
FlagMinGasPrices, "", FlagMinGasPrices, "",
"Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)",
@ -89,6 +109,27 @@ which accepts a path for the resulting pprof file.
return cmd return cmd
} }
// checkPruningParams checks that the provided pruning params are correct
func checkPruningParams() error {
if !viper.IsSet(flagPruning) && !viper.IsSet(flagPruningKeepEvery) && !viper.IsSet(flagPruningSnapshotEvery) {
return nil
}
if viper.IsSet(flagPruning) {
if viper.IsSet(flagPruningKeepEvery) || viper.IsSet(flagPruningSnapshotEvery) {
return errPruningWithGranularOptions
}
return nil
}
if !(viper.IsSet(flagPruningKeepEvery) && viper.IsSet(flagPruningSnapshotEvery)) {
return errPruningGranularOptions
}
return nil
}
func startStandAlone(ctx *Context, appCreator AppCreator) error { func startStandAlone(ctx *Context, appCreator AppCreator) error {
addr := viper.GetString(flagAddress) addr := viper.GetString(flagAddress)
home := viper.GetString("home") home := viper.GetString("home")

104
server/start_test.go Normal file
View File

@ -0,0 +1,104 @@
package server
import (
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestPruningOptions(t *testing.T) {
startCommand := StartCmd(nil, nil)
tests := []struct {
name string
paramInit func()
returnsErr bool
expectedErr error
}{
{
name: "none set, returns nil and will use default from flags",
paramInit: func() {},
returnsErr: false,
expectedErr: nil,
},
{
name: "only keep-every provided",
paramInit: func() {
viper.Set(flagPruningKeepEvery, 12345)
},
returnsErr: true,
expectedErr: errPruningGranularOptions,
},
{
name: "only snapshot-every provided",
paramInit: func() {
viper.Set(flagPruningSnapshotEvery, 12345)
},
returnsErr: true,
expectedErr: errPruningGranularOptions,
},
{
name: "pruning flag with other granular options 1",
paramInit: func() {
viper.Set(flagPruning, "set")
viper.Set(flagPruningSnapshotEvery, 1234)
},
returnsErr: true,
expectedErr: errPruningWithGranularOptions,
},
{
name: "pruning flag with other granular options 2",
paramInit: func() {
viper.Set(flagPruning, "set")
viper.Set(flagPruningKeepEvery, 1234)
},
returnsErr: true,
expectedErr: errPruningWithGranularOptions,
},
{
name: "pruning flag with other granular options 3",
paramInit: func() {
viper.Set(flagPruning, "set")
viper.Set(flagPruningKeepEvery, 1234)
viper.Set(flagPruningSnapshotEvery, 1234)
},
returnsErr: true,
expectedErr: errPruningWithGranularOptions,
},
{
name: "only prunning set",
paramInit: func() {
viper.Set(flagPruning, "set")
},
returnsErr: false,
expectedErr: nil,
},
{
name: "only granular set",
paramInit: func() {
viper.Set(flagPruningSnapshotEvery, 12345)
viper.Set(flagPruningKeepEvery, 12345)
},
returnsErr: false,
expectedErr: nil,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
viper.Reset()
tt.paramInit()
err := startCommand.PreRunE(nil, nil)
if tt.returnsErr {
require.EqualError(t, err, tt.expectedErr.Error())
} else {
require.NoError(t, err)
}
})
}
}