documents_db.rs
Overview
This file defines core data structures and an interface trait related to the storage and retrieval of blockchain archival records within a document-oriented database context. It focuses on representing blockchain data entities such as blocks, transactions, accounts, and messages in a serialized or database-storable format. The primary purpose is to provide an abstraction layer for inserting these entities into a database, with error handling and concurrency support.
The file interacts closely with the sqlite module, from which it imports entity definitions (ArchBlock, ArchTransaction, ArchAccount, ArchMessage). These entities represent the archival forms of blockchain components, which are persisted and manipulated via implementations of the DocumentsDb trait.
Data Structures
SerializedItem
#[derive(Clone, Debug)]
pub struct SerializedItem {
pub id: String,
pub data: serde_json::Value,
}
Purpose: Represents a generic serialized item with an identifier and JSON data payload. This struct is useful for handling arbitrary serialized blockchain data items in a unified way.
Fields:
id: String— A unique identifier for the item.data: serde_json::Value— The serialized content represented as JSON.
Usage Example:
let item = SerializedItem {
id: "block123".to_string(),
data: serde_json::json!({"height": 123, "hash": "abc123"}),
};
println!("{:?}", item);
DBStoredRecord
pub enum DBStoredRecord {
Block(Box<ArchBlock>),
Transactions(Vec<ArchTransaction>),
Accounts(Vec<ArchAccount>),
Messages(Vec<ArchMessage>),
}
Purpose: Enum encapsulating different types of blockchain archival records stored in the database.
Variants:
Block(Box<ArchBlock>)— A single block record.Transactions(Vec<ArchTransaction>)— A list of transaction records.Accounts(Vec<ArchAccount>)— A list of account records.Messages(Vec<ArchMessage>)— A list of message records.
Implementation Details:
Uses Rust's
Boxto heap-allocate theArchBlockfor size efficiency.Implements a custom
Debugtrait to provide concise debug output indicating the type and count of stored items.
Debug Formatting:
impl fmt::Debug for DBStoredRecord {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
DBStoredRecord::Block(val) => write!(f, "Block({})", val.id),
DBStoredRecord::Transactions(val) => write!(f, "Transactions({})", val.len()),
DBStoredRecord::Accounts(val) => write!(f, "Accounts({})", val.len()),
DBStoredRecord::Messages(val) => write!(f, "Messages({})", val.len()),
}
}
}
This allows for output like Block(abc123) or Transactions(10) during debugging.
Trait: DocumentsDb
pub trait DocumentsDb: Send + Sync {
fn put_block(&self, item: ArchBlock) -> anyhow::Result<()>;
fn put_accounts(&self, items: Vec<ArchAccount>) -> anyhow::Result<()>;
fn put_messages(&self, items: Vec<ArchMessage>) -> anyhow::Result<()>;
fn put_transactions(&self, items: Vec<ArchTransaction>) -> anyhow::Result<()>;
fn has_delivery_problems(&self) -> bool;
}
Purpose: Defines an interface for persistence operations on the archival blockchain documents.
Concurrency: The trait requires implementors to be thread-safe (
Send + Sync), allowing safe shared access in multi-threaded environments.Methods:
put_block(item: ArchBlock) -> Result<()>
Inserts or updates a single archival block into the database.put_accounts(items: Vec<ArchAccount>) -> Result<()>
Inserts or updates multiple archival account records.put_messages(items: Vec<ArchMessage>) -> Result<()>
Inserts or updates multiple archival message records.put_transactions(items: Vec<ArchTransaction>) -> Result<()>
Inserts or updates multiple archival transaction records.has_delivery_problems() -> bool
Indicates if there are any outstanding delivery or synchronization issues with the database.
Return Values:
Allput_*methods return aResult<(), anyhow::Error>indicating success or failure, facilitating robust error propagation.Usage Example:
fn store_block(db: &impl DocumentsDb, block: ArchBlock) -> anyhow::Result<()> {
db.put_block(block)?;
Ok(())
}
Implementation Details and Algorithms
The file does not implement concrete database logic but defines the contract via
DocumentsDb.Serialization is represented generically through
SerializedItemusingserde_json, allowing flexible JSON-based document representation.The use of boxed and vector-wrapped types in
DBStoredRecordoptimizes memory usage and clarifies the distinction between single and multiple records.Debug formatting is custom implemented for clear and concise output during development and logging.
Interactions with Other Modules
Imports types
ArchBlock,ArchTransaction,ArchAccount, andArchMessagefrom a sibling modulesqlite. These types represent the persistent archival schema of blockchain data.Acts as an abstraction layer over
sqlite-based storage, potentially allowing other database backends implementingDocumentsDb.The trait
DocumentsDbis intended to be implemented by concrete database access layers that handle storage and retrieval of archival blockchain records.The serialized forms and stored record enums help bridge serialization, storage, and application logic layers.
Diagram: Structure of documents_db.rs
classDiagram
class SerializedItem {
+id: String
+data: JSON Value
}
class DBStoredRecord {
<<enum>>
+Block: ArchBlock (boxed)
+Transactions: Vec<ArchTransaction>
+Accounts: Vec<ArchAccount>
+Messages: Vec<ArchMessage>
}
class DocumentsDb {
<<trait>>
+put_block()
+put_accounts()
+put_messages()
+put_transactions()
+has_delivery_problems()
}
SerializedItem --> "uses" JSON
DBStoredRecord --> ArchBlock
DBStoredRecord --> ArchTransaction
DBStoredRecord --> ArchAccount
DBStoredRecord --> ArchMessage
This diagram illustrates the main data structures and the interface trait, showing their properties and relationships to the imported archival types.