Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Declarative, type-safe handling of RocksDB key/value encoding/decoding (
#682)⚠️ This builds on top of #677 This is a 100% pure refactoring. It adds a piece of infra next to our RocksDB layer, and uses it for **all** DB access. ### Why refactor our DB access logic? The approach so far was error-prone: - When working on #677 I found a months-old bug where we stored a `scrypto_encode<LocalTransactionExecution>` to a CF and then tried to read `scrypto_decode< LocalTransactionReceipt>`. - I thought "of course we gotta be careful with what types we serialize, doh", and then in that same PR, I introduced a very similar bug myself (I stored a versioned wrapper, but was trying to read a non-versioned struct) and spent hours debugging. ### How that infra changes the DB access logic? **Before:** ``` self.db .get_cf( self.cf_handle(&StateVersionToCommittedTransactionIdentifiers), state_version.to_bytes(), ) .expect("DB error loading identifiers") .map(|v| { scrypto_decode::<VersionedCommittedTransactionIdentifiers>(&v) .expect("Failed to decode identifiers") .into_latest() }) ``` **After:** ``` self.cfs.committed_transaction_identifiers().get(&state_version) ``` ### What does it give us? Apart from the line count: - No need to remember that `state_version.to_bytes()` is THE way to encode a `StateVersion` key in the DB. - No way to confuse what type is stored in that table. - No need to remember about unwrapping a versioning wrapper. ### Cool, but you had to implement `self.cfs.committed_transaction_identifiers()` somehow first, right? Yes, but it is 100% declarative, in one place: ``` pub fn committed_transaction_identifiers( &self, ) -> impl TypedCfApi<StateVersion, CommittedTransactionIdentifiers> { // see key and value types self.create_with_codecs( StateVersionToCommittedTransactionIdentifiers, // declare which ColumnFamily it is StateVersionDbCodec::default(), // use this codec for the state version VersionedDbCodec::new( // apply auto-version-wrapping/unwrapping SborDbCodec::<VersionedCommittedTransactionIdentifiers>::default(), // use SBOR ), ) } ```
- Loading branch information