Expand description
Database handling Core Fedimint database traits and types
This module provides the core key-value database for Fedimint.
§Usage
To use the database, you typically follow these steps:
- Create a
Database
instance - Begin a transaction
- Perform operations within the transaction
- Commit the transaction
§Example
use fedimint_core::db::mem_impl::MemDatabase;
use fedimint_core::db::{Database, DatabaseTransaction, IDatabaseTransactionOpsCoreTyped};
use fedimint_core::encoding::{Decodable, Encodable};
use fedimint_core::impl_db_record;
use fedimint_core::module::registry::ModuleDecoderRegistry;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
pub struct TestKey(pub u64);
#[derive(Debug, Encodable, Decodable, Eq, PartialEq, PartialOrd, Ord)]
pub struct TestVal(pub u64);
#[repr(u8)]
#[derive(Clone)]
pub enum TestDbKeyPrefix {
Test = 0x42,
}
impl_db_record!(
key = TestKey,
value = TestVal,
db_prefix = TestDbKeyPrefix::Test,
);
// Create a new in-memory database
let db = Database::new(MemDatabase::new(), ModuleDecoderRegistry::default());
// Begin a transaction
let mut tx = db.begin_transaction().await;
// Perform operations
tx.insert_entry(&TestKey(1), &TestVal(100)).await;
let value = tx.get_value(&TestKey(1)).await;
// Commit the transaction
tx.commit_tx().await;
// For operations that may need to be retried due to conflicts, use the
// `autocommit` function:
db.autocommit(
|dbtx, _| {
Box::pin(async move {
dbtx.insert_entry(&TestKey(1), &TestVal(100)).await;
anyhow::Ok(())
})
},
None,
)
.await
.unwrap();
§Isolation of database transactions
Fedimint requires that the database implementation implement Snapshot Isolation. Snapshot Isolation is a database isolation level that guarantees consistent reads from the time that the snapshot was created (at transaction creation time). Transactions with Snapshot Isolation level will only commit if there has been no write to the modified keys since the snapshot (i.e. write-write conflicts are prevented).
Specifically, Fedimint expects the database implementation to prevent the following anomalies:
Non-Readable Write: TX1 writes (K1, V1) at time t but cannot read (K1, V1) at time (t + i)
Dirty Read: TX1 is able to read TX2’s uncommitted writes.
Non-Repeatable Read: TX1 reads (K1, V1) at time t and retrieves (K1, V2) at time (t + i) where V1 != V2.
Phantom Record: TX1 retrieves X number of records for a prefix at time t and retrieves Y number of records for the same prefix at time (t + i).
Lost Writes: TX1 writes (K1, V1) at the same time as TX2 writes (K1, V2). V2 overwrites V1 as the value for K1 (write-write conflict).
| Type | Non-Readable Write | Dirty Read | Non-Repeatable Read | Phantom Record | Lost Writes | | –––– | —————— | ––––– | —————–– | ––––––– | ———– | | MemoryDB | Prevented | Prevented | Prevented | Prevented | Possible | | RocksDB | Prevented | Prevented | Prevented | Prevented | Prevented | | Sqlite | Prevented | Prevented | Prevented | Prevented | Prevented |
Modules§
Structs§
- Base
Database 🔒 - Base functionality around
IRawDatabase
to make it aIDatabase
- Base
Database 🔒Transaction - Struct that implements
IRawDatabaseTransaction
and can be wrapped easier in other structs since it does not consumedself
by move. - Commit
Tracker 🔒 - A helper for tracking and logging on
Drop
any instances of uncommitted writes - Committable
- Session type for
DatabaseTransaction
that is allowed to commit - Database
- A public-facing newtype over
IDatabase
- Database
Transaction - A high level database transaction handle
- Database
Version - Database
Version Key - Database
Version KeyV0 - Deprecated: Use
DatabaseVersionKey(ModuleInstanceId)
instead. - DbKey
Prefix Iter - An iterator over the variants of DbKeyPrefix
- GlobalDB
TxAccess Token - Code used to access
global_dbtx
- Migration
Context - NonCommittable
- Session type for a
DatabaseTransaction
that is not allowed to commit - Prefix
Database 🔒 - A database that wraps an
inner
one and adds a prefix to all operations, effectively creating an isolated partition. - Prefix
Database 🔒Transaction - A database transactions that wraps an
inner
one and adds a prefix to all operations, effectively creating an isolated partition.
Enums§
- Autocommit
Error - Error returned when the autocommit function fails
- DbKey
Prefix - Decoding
Error - Maybe
Ref 🔒 - Test
DbKey Prefix
Constants§
Traits§
- Database
Key DatabaseKey
that represents the lookup structure for retrieving key/value pairs from the database.- Database
KeyPrefix - Database
KeyWith Notify - Marker trait for
DatabaseKey
s whereNOTIFY
is true - Database
Lookup - A key that can be used to query one or more
DatabaseRecord
ExtendsDatabaseKeyPrefix
to prepend the key’s prefix. - Database
Record - A key + value pair in the database with a unique prefix
Extends
DatabaseKeyPrefix
to prepend the key’s prefix. - Database
Value DatabaseValue
that represents the value structure of database records.- IDatabase
- A database that on top of a raw database operation, implements key notification system.
- IDatabase
Transaction - Fedimint database transaction
- IDatabase
Transaction Ops - Additional operations (only some) database transactions expose, on top of
IDatabaseTransactionOpsCore
- IDatabase
Transaction OpsCore - Core raw a operations database transactions supports
- IDatabase
Transaction OpsCore Typed - Like
IDatabaseTransactionOpsCore
, but typed - IRaw
Database - Raw database implementation
- IRaw
Database Ext - An extension trait with convenience operations on
IRawDatabase
- IRaw
Database Transaction - Raw database transaction (e.g. rocksdb implementation)
- With
Decoders - A database type that has decoders, which allows it to implement
IDatabaseTransactionOpsCoreTyped
Functions§
- apply_
migrations - apply_
migrations_ dbtx apply_migrations
iterates from the on disk database version for the module.- apply_
migrations_ server - See
apply_migrations_server_dbtx
- apply_
migrations_ server_ dbtx - Applies the database migrations to a non-isolated database.
- create_
database_ version - create_
database_ version_ dbtx - Creates the
DatabaseVersion
inside the database if it does not exist. If necessary, this function will migrate the legacy database version to the expectedDatabaseVersionKey
. - decode_
key_ 🔒expect - decode_
value 🔒 - decode_
value_ 🔒expect - expect_
write_ conflict - find_
by_ prefix_ sorted_ descending - future_
returns_ shortly - get_
current_ database_ version - Verifies that all database migrations are defined contiguously and returns the “current” database version, which is one greater than the last key in the map.
- module_
instance_ 🔒id_ or_ global - Helper function to retrieve the
module_instance_id
for modules, otherwise return 0xff for the global namespace. - module_
instance_ 🔒id_ to_ byte_ prefix - remove_
current_ 🔒db_ version_ if_ exists - Removes
DatabaseVersion
fromDatabaseVersionKeyV0
if it exists and returns the current database version. If the current version does not exist, usetarget_db_version
if the database is new. Otherwise, returnDatabaseVersion(0)
to ensure all migrations are run. - verify_
commit - verify_
find_ by_ prefix - verify_
find_ by_ range - verify_
insert_ elements - verify_
module_ db - verify_
module_ prefix - verify_
phantom_ entry - verify_
prevent_ dirty_ reads - verify_
prevent_ nonrepeatable_ reads - verify_
read_ own_ writes - verify_
remove_ by_ prefix - verify_
remove_ existing - verify_
remove_ nonexisting - verify_
rollback_ to_ savepoint - verify_
snapshot_ isolation - verify_
string_ prefix
Type Aliases§
- Core
Migration Fn CoreMigrationFn
that modules can implement to “migrate” the database to the next database version.- Phantom
Bound - Just ignore this type, it’s only there to make compiler happy
- Prefix
Stream