implement CommitKVStore using a migration router#3382
implement CommitKVStore using a migration router#3382cody-littley wants to merge 3 commits intomainfrom
Conversation
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3382 +/- ##
=======================================
Coverage 59.08% 59.09%
=======================================
Files 2099 2100 +1
Lines 172988 173030 +42
=======================================
+ Hits 102212 102251 +39
- Misses 61911 61914 +3
Partials 8865 8865
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
| // Close is illegal during the standard CommitKVStore lifecycle for this type: | ||
| // the wrapped Router is owned by the caller and must outlive this view. | ||
| func (r *RouterCommitKVStore) Close() error { | ||
| return fmt.Errorf("RouterCommitKVStore.Close: illegal during standard lifecycle") |
There was a problem hiding this comment.
should we panic instead of error here to match testing?
There was a problem hiding this comment.
Test was incorrect, and actually failing. Fixed the test. IMO, better to return error than to panic, especially when the interface already has an error return value.
| router Router, | ||
| storeName string, | ||
| versionProvider func() int64, | ||
| ) *RouterCommitKVStore { |
There was a problem hiding this comment.
context.Background() is hardcoded, do we need any outer ctx for per-Set cancellation? not sure
There was a problem hiding this comment.
In the main feature branch where I've got all of this code integrated, I actually removed the goroutines from the routers (race conditions + premature optimization 😅). Would you be ok with me addressing that issue in the feature branch instead of here? I can make the next follow up PR be the one that contains those changes.
| } | ||
|
|
||
| func (r *RouterCommitKVStore) Set(key []byte, value []byte) { | ||
| r.applyOne(&proto.KVPair{Key: key, Value: value}) |
There was a problem hiding this comment.
Set/Remove issues one ApplyChangeSets per call, In the prev PR, MigrationManager.ApplyChangeSets advances exactly one migration batch per call. A single cosmos-sdk transaction can issue dozens of Set calls; that becomes dozens of migration batches per commit
There was a problem hiding this comment.
As far as I can tell, there are no callers to Set() or Delete() anywhere in production code, only in unit tests.
The goal of router_kvstore.go was to implement the current interface in a way that didn't require a huge refactor. My plan after that is to incrementally remove methods (like these ones) one at a time, until the entire CommitKVStore interface can be fully deleted.
I added the following documentation to telegraph our intentions:
// Planed for future deprecation but not yet deprecated.
type CommitKVStore interface {
// Planed for future deprecation but not yet deprecated.
// This is the proper method to call to get a value from the store.
Get(key []byte) []byte
// Planed for future deprecation but not yet deprecated. This is the proper method to call to check
// if a key exists in the store.
Has(key []byte) bool
// Deprected: do not call in production code, use CommitKVStore.ApplyChangeSets() instead.
Set(key, value []byte)
// Deprected: do not call in production code, use CommitKVStore.ApplyChangeSets() instead.
Remove(key []byte)
// Deprected but safe to call
Version() int64
// Deprected: do not call in production code, may panic on stores backed by flatKV
RootHash() []byte
// Partially deprecated: may panic if called on a store that does not support iteration (e.g. evm/ after migration)
Iterator(start, end []byte, ascending bool) dbm.Iterator
// Partially deprecated: may panic if called on a store that does not support proofs (e.g. evm/ after migration)
GetProof(key []byte) *ics23.CommitmentProof
// deprecated: some implementations always return errors, and ones that don't mean you are closing something
// that shouldn't be closed directly
io.Closer
}
|
|
||
| func (r *RouterCommitKVStore) Set(key []byte, value []byte) { | ||
| r.applyOne(&proto.KVPair{Key: key, Value: value}) | ||
| } |
There was a problem hiding this comment.
Sei KVStore impls (storev2/commitment/Store.Set, cachekv.Set) only append to an in-memory changeset; the real write happens at Commit.
how about RouterCommitKVStore buffers writes and flushes once at commit time (needs a Commit/Flush hook, mirroring storev2/commitment/Store).
There was a problem hiding this comment.
I think this topic is probably worth a discussion. Currently FlatKV also only writes to an in-memory buffer.
This Set() method isn't used in production, only unit tests. And the plan is to delete it. My current goal is to make unit tests pass, and I'm less concerned with performance implications.
There was a problem hiding this comment.
Could you add me to this discussion?
| return found | ||
| } | ||
|
|
||
| func (r *RouterCommitKVStore) Set(key []byte, value []byte) { |
There was a problem hiding this comment.
how do we ensure this actually works instead of baseapp wraps runTx in recover() and turns the panic into a per-tx error, then keeps processing
// If this method returns an error, it is not safe to attempt to retry. An error should be considered // fatal, and should result in any managed databases being shut down and crash recovered.
There was a problem hiding this comment.
We should discuss this with execution folk. They should NEVER treat a DB error/panic as a transaction failure, as continuing after an error probably means data corruption and a later app hash break.
Describe your changes and provide context
Implement the
CommitKVStoreinterface using amigration.Router. This will allow us to implement the composite DB'sGetChildStoreByName()method.Note that this is not a permanent solution. The long term solution will be to remove the
GetChildStoreByName()api entirely. But that can be an incremental cleanup, and does not block MVP deployment.Testing performed to validate your change
unit tests