-
Notifications
You must be signed in to change notification settings - Fork 886
feat(seidb): add state store snapshots #3889
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
base: main
Are you sure you want to change the base?
Changes from all commits
b4e5314
bf557f4
23e9796
48f7ea8
b3b7ed4
83885c5
7f21bed
d716ff6
14a7962
50ba6e3
5d1e675
183f87b
06df0ff
de05dd5
144059b
9d06701
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ import ( | |
| "github.com/sei-protocol/sei-chain/sei-db/state_db/sc/hashlog" | ||
| sctypes "github.com/sei-protocol/sei-chain/sei-db/state_db/sc/types" | ||
| "github.com/sei-protocol/sei-chain/sei-db/state_db/ss" | ||
| sscomposite "github.com/sei-protocol/sei-chain/sei-db/state_db/ss/composite" | ||
| abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types" | ||
| dbm "github.com/tendermint/tm-db" | ||
| ) | ||
|
|
@@ -48,10 +49,24 @@ var ( | |
| _ types.Queryable = (*Store)(nil) | ||
| ) | ||
|
|
||
| // stateStoreSnapshotScheduler is the commit path's half of the SS snapshot | ||
| // contract: flush tells the state store which version it has just finished | ||
| // enqueueing, and the store decides whether that version is a boundary. | ||
| type stateStoreSnapshotScheduler interface { | ||
| ScheduleSnapshot(version int64) | ||
| } | ||
|
|
||
| // ss.NewStateStore returns the interface, so the capability is resolved by type | ||
| // assertion at startup. This pins the only implementation, so wrapping the state | ||
| // store without carrying the method through fails the build here rather than | ||
| // silently ending SS snapshots at runtime. | ||
| var _ stateStoreSnapshotScheduler = (*sscomposite.CompositeStateStore)(nil) | ||
|
|
||
| type Store struct { | ||
| mtx sync.RWMutex | ||
| scStore sctypes.Committer | ||
| ssStore seidbtypes.StateStore | ||
| ssSnapshots stateStoreSnapshotScheduler | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the future, we will have a global snapshot scheduler to manage both SC and SS snapshot, but I think it's fine to keep as it is today until MemIAVL is fully gone |
||
| lastCommitInfo *types.CommitInfo | ||
| storesParams map[types.StoreKey]storeParams | ||
| storeKeys map[string]types.StoreKey | ||
|
|
@@ -136,6 +151,7 @@ func NewStore( | |
| scDir: scDir, | ||
| } | ||
| if ssConfig.Enable { | ||
| config.AlignSSSnapshotWithSC(scConfig, &ssConfig) | ||
| ssStore, err := ss.NewStateStore(homeDir, ssConfig) | ||
| if err != nil { | ||
| panic(err) | ||
|
|
@@ -150,6 +166,16 @@ func NewStore( | |
| panic("Enabling SS store without state sync could cause data corruption") | ||
| } | ||
| store.ssStore = ssStore | ||
| scheduler, ok := ssStore.(stateStoreSnapshotScheduler) | ||
| if !ok { | ||
| // Unreachable while CompositeStateStore is the only implementation, | ||
| // which the assertion above pins. Log rather than drop silently, so | ||
| // a wrapper that loses the method is visible as a boot line instead | ||
| // of as snapshots that never appear. | ||
| logger.Error("state store does not schedule snapshots; SS snapshots are disabled", | ||
| "type", fmt.Sprintf("%T", ssStore)) | ||
| } | ||
| store.ssSnapshots = scheduler | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] This is correct but leans on a subtlety worth making explicit: on a failed type assertion |
||
| } | ||
| return store | ||
|
|
||
|
|
@@ -255,6 +281,14 @@ func (rs *Store) flush() error { | |
| telemetry.SetGauge(float32(currentVersion), "storeV2", "ss", "version") | ||
| } | ||
| } | ||
| // Both branches above have finished handing currentVersion to SS and have | ||
| // enqueued nothing above it, which is what makes an SS snapshot label exact. | ||
| // Triggering here rather than inside either branch keeps populated and empty | ||
| // blocks on one path. A repeat within the same block (flush runs twice, and | ||
| // the second pass sees an empty changeset) is ignored by the state store. | ||
| if rs.ssSnapshots != nil { | ||
| rs.ssSnapshots.ScheduleSnapshot(currentVersion) | ||
| } | ||
| return rs.scStore.ApplyChangeSets(changeSets) | ||
| } | ||
|
|
||
|
|
||
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.
Why do we need this config at all? We should make SS default always taking snapshots right? (In order to support rollback)