pub struct Database { /* private fields */ }Expand description
Represents a collection of related entries, like a traditional database or a branch in a version control system.
Each Database is identified by the ID of its root Entry and manages the history of data
associated with that root. It interacts with the underlying storage through the Instance handle.
Implementations§
Source§impl Database
impl Database
Sourcepub async fn create(
instance: &Instance,
signing_key: PrivateKey,
initial_settings: Doc,
) -> Result<Self>
pub async fn create( instance: &Instance, signing_key: PrivateKey, initial_settings: Doc, ) -> Result<Self>
Creates a new Database instance with a user-provided signing key.
This constructor creates a new database using a signing key that’s already in memory (e.g., from UserKeyManager), without requiring the key to be stored in the backend. This is the preferred method for creating databases in a User context where keys are managed separately from the backend.
The created database will use a DatabaseKey for all subsequent operations,
meaning transactions will use the provided key directly rather than looking it up
from backend storage.
§Auth Bootstrapping
Auth is always bootstrapped with the signing key as Admin(0). Passing auth
configuration in initial_settings is an error — additional keys must be added
via follow-up transactions after creation.
§Arguments
instance- Instance handle for storage and coordinationsigning_key- The signing key to use for the initial commit and subsequent operations. This key should already be decrypted and ready to use. The public key is derived automatically and used as the key identifier in auth settings.initial_settings-DocCRDT containing the initial settings for the database. UseDoc::new()for an empty settings document.
§Returns
A Result containing the new Database instance configured with a DatabaseKey.
§Example
let instance = Instance::open(Box::new(InMemory::new())).await?;
let (signing_key, _public_key) = generate_keypair();
let mut settings = Doc::new();
settings.set("name", "my_database");
// Create database with user-managed key (no backend storage needed)
let database = Database::create(&instance, signing_key, settings).await?;
// All transactions automatically use the provided key
let tx = database.new_transaction().await?;Sourcepub async fn open(
instance: Instance,
root_id: &ID,
key: DatabaseKey,
) -> Result<Self>
pub async fn open( instance: Instance, root_id: &ID, key: DatabaseKey, ) -> Result<Self>
Opens an existing Database with a DatabaseKey.
This constructor opens an existing database by its root ID and configures it to use
a DatabaseKey for all subsequent operations. This is used in the User
context where keys are managed by UserKeyManager and already decrypted in memory.
§Key Management
This constructor uses user-managed keys:
- The key is provided directly (e.g., from UserKeyManager)
- Uses
DatabaseKeyfor all subsequent operations - No backend key storage needed
Note: To create a new database with user-managed keys, use create().
This method is for opening existing databases.
To discover which SigKey to use for a given public key, use Database::find_sigkeys().
§Arguments
instance- Instance handle for storage and coordinationroot_id- The root entry ID of the existing database to openkey- ADatabaseKeycombining signing key and auth identity
§Returns
A Result containing the Database instance configured with the DatabaseKey
§Example
// Open database with pubkey identity (most common)
let key = DatabaseKey::new(signing_key);
let database = Database::open(instance, &root_id, key).await?;
// All transactions automatically use the provided key
let tx = database.new_transaction().await?;Sourcepub async fn find_sigkeys(
instance: &Instance,
root_id: &ID,
pubkey: &PublicKey,
) -> Result<Vec<(SigKey, Permission)>>
pub async fn find_sigkeys( instance: &Instance, root_id: &ID, pubkey: &PublicKey, ) -> Result<Vec<(SigKey, Permission)>>
Find all SigKeys that a public key can use to access a database.
This static helper method loads a database’s authentication settings and returns all possible SigKeys that can be used with the given public key. This is useful for discovering authentication options before opening a database.
Returns all matching SigKeys including:
- Specific key names where the pubkey matches
- Global permission if available
- Single-hop delegation paths (pubkey found in a directly delegated tree)
The results are sorted by permission level, highest first, making it easy to select the most privileged access available.
§Arguments
instance- Instance handle for storage and coordinationroot_id- Root entry ID of the database to checkpubkey- Public key string (e.g., “Ed25519:abc123…”) to look up
§Returns
A vector of (SigKey, Permission) tuples, sorted by permission (highest first). Returns empty vector if no valid access methods are found.
§Errors
Returns an error if:
- Database cannot be loaded
- Auth settings cannot be parsed
§Example
// Find all SigKeys this pubkey can use (sorted highest permission first)
let sigkeys = Database::find_sigkeys(&instance, &root_id, &pubkey).await?;
// Use the first available SigKey (highest permission)
if let Some((sigkey, _permission)) = sigkeys.first() {
let key = DatabaseKey::with_identity(signing_key, sigkey.clone());
let database = Database::open(instance, &root_id, key).await?;
}Sourcepub fn auth_identity(&self) -> Option<&SigKey>
pub fn auth_identity(&self) -> Option<&SigKey>
Get the auth identity for this database’s configured key.
Sourcepub fn on_local_write<F, Fut>(&self, callback: F) -> Result<()>
pub fn on_local_write<F, Fut>(&self, callback: F) -> Result<()>
Register an Instance-wide callback to be invoked when entries are written locally to this database.
Local writes are those originating from transaction commits in the current Instance. The callback receives the entry, database, and instance as parameters, providing full context for any coordination or side effects needed.
Important: This callback is registered at the Instance level and will fire for all local writes to the database tree (identified by root ID), regardless of which Database handle performed the write. Multiple Database handles pointing to the same root ID share the same set of callbacks.
§Arguments
callback- Function to invoke on local writes to this database tree
§Returns
A Result indicating success or failure
§Example
let instance = Instance::open(Box::new(InMemory::new())).await?;
database.on_local_write(|entry, db, _instance| {
let entry_id = entry.id().clone();
let db_id = db.root_id().clone();
Box::pin(async move {
println!("Entry {} written to database {}", entry_id, db_id);
Ok(())
})
})?;Sourcepub fn on_remote_write<F, Fut>(&self, callback: F) -> Result<()>
pub fn on_remote_write<F, Fut>(&self, callback: F) -> Result<()>
Register an Instance-wide callback to be invoked when entries are written remotely to this database.
Remote writes are those originating from sync or replication from other nodes. The callback receives the entry, database, and instance as parameters.
Important: This callback is registered at the Instance level and will fire for all remote writes to the database tree (identified by root ID), regardless of which Database handle registered the callback. Multiple Database handles pointing to the same root ID share the same set of callbacks.
§Arguments
callback- Function to invoke on remote writes to this database tree
§Returns
A Result indicating success or failure
§Example
let instance = Instance::open(Box::new(InMemory::new())).await?;
database.on_remote_write(|entry, db, _instance| {
let entry_id = entry.id().clone();
let db_id = db.root_id().clone();
Box::pin(async move {
println!("Remote entry {} synced to database {}", entry_id, db_id);
Ok(())
})
})?;Sourcepub async fn get_settings(&self) -> Result<SettingsStore>
pub async fn get_settings(&self) -> Result<SettingsStore>
Get a read-only settings store for the database.
Returns a SettingsStore that provides access to the database’s settings. Since this creates an internal transaction that is never committed, any modifications made through the returned store will not persist.
For making persistent changes to settings, create a transaction and use
Transaction::get_settings() instead.
§Returns
A Result containing the SettingsStore for settings or an error.
§Example
// Read-only access
let settings = database.get_settings().await?;
let name = settings.get_name().await?;
// For modifications, use a transaction:
let txn = database.new_transaction().await?;
let settings = txn.get_settings()?;
settings.set_name("new_name").await?;
txn.commit().await?;Sourcepub async fn get_name(&self) -> Result<String>
pub async fn get_name(&self) -> Result<String>
Get the name of the database from its settings store
Sourcepub async fn new_transaction(&self) -> Result<Transaction>
pub async fn new_transaction(&self) -> Result<Transaction>
Create a new atomic transaction on this database
This creates a new atomic transaction containing a new Entry. The atomic transaction will be initialized with the current state of the database. If a default authentication key is set, the transaction will use it for signing.
§Returns
A Result<Transaction> containing the new atomic transaction
Sourcepub async fn new_transaction_with_tips(
&self,
tips: impl AsRef<[ID]>,
) -> Result<Transaction>
pub async fn new_transaction_with_tips( &self, tips: impl AsRef<[ID]>, ) -> Result<Transaction>
Create a new atomic transaction on this database with specific parent tips
This creates a new atomic transaction that will have the specified entries as parents instead of using the current database tips. This allows creating complex DAG structures like diamond patterns for testing and advanced use cases.
§Arguments
tips- The specific parent tips to use for this transaction
§Returns
A Result<Transaction> containing the new atomic transaction
Sourcepub async fn insert_raw(&self, entry: Entry) -> Result<ID>
pub async fn insert_raw(&self, entry: Entry) -> Result<ID>
Insert an entry into the database without modifying it. This is primarily for testing purposes or when you need full control over the entry. Note: This method assumes the entry is already properly signed and verified.
Sourcepub async fn get_store_viewer<T>(&self, name: impl Into<String>) -> Result<T>where
T: Store,
pub async fn get_store_viewer<T>(&self, name: impl Into<String>) -> Result<T>where
T: Store,
Get a Store type that will handle accesses to the Store This will return a Store initialized to point at the current state of the database.
The returned store should NOT be used to modify the database, as it intentionally does not expose the Transaction. Since the Transaction is never committed, it does not have any effect on the database.
Sourcepub async fn get_tips(&self) -> Result<Vec<ID>>
pub async fn get_tips(&self) -> Result<Vec<ID>>
Get the current tips (leaf entries) of the main database branch.
Tips represent the latest entries in the database’s main history, forming the heads of the DAG.
§Returns
A Result containing a vector of IDs for the tip entries or an error.
Sourcepub async fn get_tip_entries(&self) -> Result<Vec<Entry>>
pub async fn get_tip_entries(&self) -> Result<Vec<Entry>>
Get the full Entry objects for the current tips of the main database branch.
§Returns
A Result containing a vector of the tip Entry objects or an error.
Sourcepub async fn get_entry<I: Into<ID>>(&self, entry_id: I) -> Result<Entry>
pub async fn get_entry<I: Into<ID>>(&self, entry_id: I) -> Result<Entry>
Get a single entry by ID from this database.
This is the primary method for retrieving entries after commit operations. It provides safe, high-level access to entry data without exposing backend details.
The method verifies that the entry belongs to this database by checking its root ID. If the entry exists but belongs to a different database, an error is returned.
§Arguments
entry_id- The ID of the entry to retrieve (accepts anything that converts to ID/String)
§Returns
A Result containing the Entry or an error if not found or not part of this database
§Example
let entry_id = txn.commit().await?;
let entry = tree.get_entry(&entry_id).await?; // Using &String
let entry = tree.get_entry("some_entry_id").await?; // Using &str
let entry = tree.get_entry(entry_id.clone()).await?; // Using String
println!("Entry signature: {:?}", entry.sig);Sourcepub async fn get_entries<I, T>(&self, entry_ids: I) -> Result<Vec<Entry>>
pub async fn get_entries<I, T>(&self, entry_ids: I) -> Result<Vec<Entry>>
Get multiple entries by ID efficiently.
This method retrieves multiple entries more efficiently than multiple get_entry() calls
by minimizing conversion overhead and pre-allocating the result vector.
The method verifies that all entries belong to this database by checking their root IDs. If any entry exists but belongs to a different database, an error is returned.
§Parameters
entry_ids- An iterable of entry IDs to retrieve. Accepts any string or ID types that can be converted toID(&str,String,&ID, etc.)
§Returns
A Result containing a vector of Entry objects or an error if any entry is not found or not part of this database
§Example
let entry_ids = vec!["id1", "id2", "id3"];
let entries = tree.get_entries(entry_ids).await?;Sourcepub async fn verify_entry_signature<I: Into<ID>>(
&self,
entry_id: I,
) -> Result<bool>
pub async fn verify_entry_signature<I: Into<ID>>( &self, entry_id: I, ) -> Result<bool>
Verify an entry’s signature and authentication against the database’s configuration that was valid at the time of entry creation.
This method validates that:
- The entry belongs to this database
- The entry is properly signed with a key that was authorized in the database’s authentication settings at the time the entry was created
- The signature is cryptographically valid
The method uses the entry’s metadata to determine which authentication settings were active when the entry was signed, ensuring that entries remain valid even if keys are later revoked or settings change.
§Arguments
entry_id- The ID of the entry to verify (accepts anything that converts to ID/String)
§Returns
A Result containing true if the entry is valid and properly authenticated, false if authentication fails
§Errors
Returns an error if:
- The entry is not found
- The entry does not belong to this database
- The entry’s metadata cannot be parsed
- The historical authentication settings cannot be retrieved
Sourcepub async fn current_permission(&self) -> Result<Permission>
pub async fn current_permission(&self) -> Result<Permission>
Get the permission level for this database’s configured signing key.
Returns the effective permission for the key that was configured when opening
or creating this database. This uses the already-resolved identity stored in
the database’s DatabaseKey, ensuring consistency with Database::open.
§Returns
The effective Permission for the configured signing key.
§Errors
Returns an error if:
- No signing key is configured (database opened without authentication)
- The database settings cannot be retrieved
- The key is no longer valid in the current auth settings
§Example
// Check if the current key has Admin permission
let permission = database.current_permission().await?;
if permission.can_admin() {
println!("Current key has Admin permission!");
}Sourcepub async fn get_all_entries(&self) -> Result<Vec<Entry>>
pub async fn get_all_entries(&self) -> Result<Vec<Entry>>
Get all entries in this database.
⚠️ Warning: This method loads all entries into memory. Use with caution on large databases.
Consider using get_tips() or get_tip_entries() for more efficient access patterns.
§Returns
A Result containing a vector of all Entry objects in the database
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Database
impl !RefUnwindSafe for Database
impl Send for Database
impl Sync for Database
impl Unpin for Database
impl !UnwindSafe for Database
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more