Session Management API Documentation¶
Version: 3.1.0 Status: Production-Ready Last Updated: 2025-12-08
Table of Contents¶
- Overview
- SessionManager API
- LockManager API
- Transaction API Updates
- DumpManager API
- Type Definitions
- Error Types
- Code Examples
- Thread Safety Guarantees
- Concurrency Patterns
- Integration Examples
Overview¶
HeliosDB-Lite v3.1.0 introduces comprehensive session management APIs for building multi-user applications with ACID transactions. The API provides:
- SessionManager: Multi-user session coordination
- LockManager: Concurrency control with deadlock detection
- Transaction API: Enhanced transaction isolation levels
- DumpManager: Programmatic dump/restore operations
Module Structure:
heliosdb_lite::
├── session::
│ ├── SessionManager # Session lifecycle management
│ ├── Session # Individual session state
│ ├── SessionId # Session identifiers
│ └── IsolationLevel # Transaction isolation levels
├── storage::
│ ├── LockManager # Lock acquisition and deadlock detection
│ ├── LockMode # Lock types (Shared, Exclusive, Update)
│ ├── DumpManager # Dump/restore operations
│ └── DirtyTracker # Dirty state tracking
└── EmbeddedDatabase # Main database interface
Minimum Rust Version: 1.75+
SessionManager API¶
Module¶
Struct Definition¶
pub struct SessionManager {
// Internal fields (private)
}
impl SessionManager {
pub fn new(config: SessionConfig) -> Self;
pub fn create_session(
&self,
user: &User,
isolation: IsolationLevel
) -> Result<SessionId, Error>;
pub fn destroy_session(&self, session_id: SessionId) -> Result<(), Error>;
pub fn begin_transaction(&self, session_id: SessionId) -> Result<TransactionId, Error>;
pub fn commit_transaction(&self, session_id: SessionId) -> Result<(), Error>;
pub fn rollback_transaction(&self, session_id: SessionId) -> Result<(), Error>;
pub fn get_session(&self, session_id: SessionId) -> Result<Arc<RwLock<Session>>, Error>;
pub fn list_active_sessions(&self) -> Vec<SessionId>;
pub fn session_count(&self) -> usize;
pub fn session_count_for_user(&self, user_id: UserId) -> usize;
}
Methods¶
SessionManager::new¶
Create a new session manager instance.
Signature:
Parameters:
- config: SessionConfig - Configuration for session management
Example:
use heliosdb_lite::session::{SessionManager, SessionConfig};
let config = SessionConfig {
timeout_secs: 3600,
max_sessions_per_user: 10,
default_isolation: IsolationLevel::ReadCommitted,
};
let manager = SessionManager::new(config);
create_session¶
Create a new user session with specified isolation level.
Signature:
Parameters:
- user: &User - User credentials and metadata
- isolation: IsolationLevel - Transaction isolation level
Returns: Result<SessionId, Error>
Errors:
- Error::AuthenticationFailed - User authentication failed
- Error::QuotaExceeded - Session limit exceeded for user
Example:
use heliosdb_lite::session::{User, IsolationLevel};
let user = User::new("alice", "password123");
let session_id = manager.create_session(&user, IsolationLevel::ReadCommitted)?;
println!("Created session: {}", session_id);
begin_transaction¶
Begin a new transaction within a session.
Signature:
Parameters:
- session_id: SessionId - Active session identifier
Returns: Result<TransactionId, Error>
Errors:
- Error::SessionNotFound - Invalid session ID
- Error::TransactionAlreadyActive - Transaction already in progress
Example:
let txn_id = manager.begin_transaction(session_id)?;
// Execute queries within transaction...
manager.commit_transaction(session_id)?;
commit_transaction¶
Commit the active transaction in a session.
Signature:
Errors:
- Error::NoActiveTransaction - No transaction to commit
- Error::SerializationFailure - Serializable isolation conflict
Example:
manager.begin_transaction(session_id)?;
// Perform database operations...
match manager.commit_transaction(session_id) {
Ok(()) => println!("Transaction committed"),
Err(Error::SerializationFailure(msg)) => {
// Retry transaction
println!("Serialization conflict: {}", msg);
}
Err(e) => return Err(e),
}
list_active_sessions¶
Get list of all active session IDs.
Signature:
Returns: Vec<SessionId> - All active sessions
Example:
let sessions = manager.list_active_sessions();
println!("Active sessions: {}", sessions.len());
for session_id in sessions {
println!(" - Session {}", session_id);
}
LockManager API¶
Module¶
Struct Definition¶
pub struct LockManager {
// Internal fields (private)
}
impl LockManager {
pub fn new(config: LockConfig) -> Self;
pub fn acquire_lock(
&self,
txn_id: TransactionId,
key: Key,
mode: LockMode
) -> Result<(), Error>;
pub fn release_lock(
&self,
txn_id: TransactionId,
key: Key
) -> Result<(), Error>;
pub fn release_all_locks(&self, txn_id: TransactionId) -> Result<(), Error>;
pub fn has_lock(
&self,
txn_id: TransactionId,
key: &Key,
mode: LockMode
) -> bool;
pub fn detect_deadlock(&self, txn_id: TransactionId) -> Result<bool, Error>;
}
Enums¶
LockMode¶
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum LockMode {
Shared, // Read lock (S)
Exclusive, // Write lock (X)
Update, // Intent to update (U)
}
impl LockMode {
pub fn is_compatible(&self, other: LockMode) -> bool;
}
Lock Compatibility Matrix:
Methods¶
acquire_lock¶
Acquire a lock on a key with specified mode.
Signature:
Parameters:
- txn_id: TransactionId - Transaction acquiring lock
- key: Key - Resource to lock (table, row, page)
- mode: LockMode - Lock type
Errors:
- Error::LockTimeout - Timeout waiting for lock
- Error::Deadlock - Deadlock detected
Example:
use heliosdb_lite::storage::{LockManager, LockMode, Key};
let lock_manager = LockManager::new(LockConfig::default());
// Acquire shared lock for read
let key = Key::row("users", 123);
lock_manager.acquire_lock(txn_id, key.clone(), LockMode::Shared)?;
// Read data...
// Upgrade to exclusive lock for write
lock_manager.acquire_lock(txn_id, key.clone(), LockMode::Exclusive)?;
// Write data...
// Release locks
lock_manager.release_all_locks(txn_id)?;
detect_deadlock¶
Check if transaction is involved in a deadlock.
Signature:
Returns: Result<bool, Error> - true if deadlock detected
Example:
if lock_manager.detect_deadlock(txn_id)? {
println!("Deadlock detected, aborting transaction");
manager.rollback_transaction(session_id)?;
}
Transaction API Updates¶
Enhanced Transaction Methods¶
use heliosdb_lite::storage::Transaction;
impl Transaction {
pub fn new(
db: Arc<StorageEngine>,
snapshot: Snapshot,
lock_manager: Arc<LockManager>
) -> Self;
pub fn set_isolation_level(&mut self, level: IsolationLevel);
pub fn get_isolation_level(&self) -> IsolationLevel;
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Error>;
pub fn put(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<(), Error>;
pub fn delete(&mut self, key: &[u8]) -> Result<(), Error>;
pub fn commit(self) -> Result<(), Error>;
pub fn rollback(self) -> Result<(), Error>;
}
Isolation Levels¶
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum IsolationLevel {
ReadCommitted,
RepeatableRead,
Serializable,
}
Example:
use heliosdb_lite::storage::{Transaction, IsolationLevel};
let mut txn = Transaction::new(db.clone(), snapshot, lock_manager.clone());
txn.set_isolation_level(IsolationLevel::Serializable);
txn.put(b"key".to_vec(), b"value".to_vec())?;
txn.commit()?;
DumpManager API¶
Module¶
Struct Definition¶
pub struct DumpManager {
// Internal fields (private)
}
impl DumpManager {
pub fn new(storage: Arc<StorageEngine>) -> Self;
pub fn dump(&self, options: DumpOptions) -> Result<DumpReport, Error>;
pub fn restore(&self, options: RestoreOptions) -> Result<RestoreReport, Error>;
pub fn list_dumps(&self) -> Result<Vec<DumpMetadata>, Error>;
pub fn verify_dump(&self, path: &Path) -> Result<bool, Error>;
}
Options Structs¶
pub struct DumpOptions {
pub output_path: PathBuf,
pub mode: DumpMode,
pub compress: bool,
pub compression_type: CompressionType,
pub tables: Option<Vec<String>>,
pub append: bool,
}
pub struct RestoreOptions {
pub input_path: PathBuf,
pub tables: Option<Vec<String>>,
pub mode: RestoreMode,
pub on_conflict: ConflictResolution,
}
#[derive(Clone, Copy)]
pub enum DumpMode {
Full,
Incremental,
}
#[derive(Clone, Copy)]
pub enum CompressionType {
None,
Lz4,
Zstd,
}
#[derive(Clone, Copy)]
pub enum RestoreMode {
Clean,
Append,
}
#[derive(Clone, Copy)]
pub enum ConflictResolution {
Error,
Skip,
Update,
}
Methods¶
dump¶
Dump database to file.
Signature:
Example:
use heliosdb_lite::storage::dump::{DumpManager, DumpOptions, DumpMode, CompressionType};
use std::path::PathBuf;
let dump_manager = DumpManager::new(storage.clone());
let options = DumpOptions {
output_path: PathBuf::from("/backups/db.heliodump"),
mode: DumpMode::Full,
compress: true,
compression_type: CompressionType::Zstd,
tables: None, // All tables
append: false,
};
let report = dump_manager.dump(options)?;
println!("Dumped {} tables, {} rows, {} bytes",
report.tables_dumped,
report.rows_dumped,
report.bytes_written
);
restore¶
Restore database from dump file.
Signature:
Example:
use heliosdb_lite::storage::dump::{RestoreOptions, RestoreMode, ConflictResolution};
let options = RestoreOptions {
input_path: PathBuf::from("/backups/db.heliodump"),
tables: None, // All tables
mode: RestoreMode::Clean,
on_conflict: ConflictResolution::Error,
};
let report = dump_manager.restore(options)?;
println!("Restored {} tables, {} rows",
report.tables_restored,
report.rows_restored
);
Type Definitions¶
SessionId¶
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct SessionId(u64);
impl SessionId {
pub fn new() -> Self;
pub fn as_u64(&self) -> u64;
}
UserId¶
TransactionId¶
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct TransactionId(u64);
impl TransactionId {
pub fn new() -> Self;
pub fn as_u64(&self) -> u64;
}
User¶
pub struct User {
pub id: UserId,
pub username: String,
pub roles: Vec<String>,
}
impl User {
pub fn new(username: impl Into<String>, password: impl AsRef<str>) -> Self;
pub fn has_role(&self, role: &str) -> bool;
}
Key¶
pub enum Key {
Table(String),
Row(String, RowId),
Page(String, PageId),
}
impl Key {
pub fn table(name: impl Into<String>) -> Self;
pub fn row(table: impl Into<String>, row_id: RowId) -> Self;
pub fn page(table: impl Into<String>, page_id: PageId) -> Self;
}
Error Types¶
Error Enum¶
#[derive(Debug)]
pub enum Error {
// Session errors
SessionNotFound(SessionId),
SessionExpired(SessionId),
QuotaExceeded(String),
// Transaction errors
TransactionAlreadyActive,
NoActiveTransaction,
SerializationFailure(String),
// Lock errors
LockTimeout,
Deadlock(String),
// Dump/restore errors
DumpError(String),
RestoreError(String),
VersionIncompatible(String),
// General errors
AuthenticationFailed,
AuthorizationFailed,
Io(std::io::Error),
Other(String),
}
impl std::fmt::Display for Error { ... }
impl std::error::Error for Error { ... }
Result Type¶
Code Examples¶
Example 1: Multi-User Application¶
use heliosdb_lite::{EmbeddedDatabase, session::*};
use std::sync::Arc;
use std::thread;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create in-memory database
let db = Arc::new(EmbeddedDatabase::new_in_memory()?);
// Create session manager
let manager = Arc::new(SessionManager::new(SessionConfig::default()));
// Setup schema
db.execute("CREATE TABLE accounts (id INT PRIMARY KEY, balance INT)")?;
db.execute("INSERT INTO accounts VALUES (1, 1000)")?;
// Spawn multiple user sessions
let mut handles = vec![];
for i in 0..10 {
let db = db.clone();
let manager = manager.clone();
let handle = thread::spawn(move || {
let user = User::new(format!("user{}", i), "password");
let session_id = manager.create_session(&user, IsolationLevel::ReadCommitted)?;
// Perform transaction
manager.begin_transaction(session_id)?;
let balance: i32 = db.query_one(
"SELECT balance FROM accounts WHERE id = 1",
&[]
)?;
db.execute(&format!(
"UPDATE accounts SET balance = {} WHERE id = 1",
balance - 10
))?;
manager.commit_transaction(session_id)?;
manager.destroy_session(session_id)?;
Ok::<_, Box<dyn std::error::Error>>(())
});
handles.push(handle);
}
// Wait for all sessions
for handle in handles {
handle.join().unwrap()?;
}
// Verify final balance
let final_balance: i32 = db.query_one(
"SELECT balance FROM accounts WHERE id = 1",
&[]
)?;
println!("Final balance: {}", final_balance); // Should be 900
Ok(())
}
Example 2: Serializable Transaction with Retry¶
use heliosdb_lite::session::*;
fn transfer_with_retry(
manager: &SessionManager,
db: &EmbeddedDatabase,
session_id: SessionId,
from_id: i32,
to_id: i32,
amount: i32,
) -> Result<(), Error> {
let max_retries = 3;
for attempt in 0..max_retries {
manager.begin_transaction(session_id)?;
match perform_transfer(db, from_id, to_id, amount) {
Ok(()) => {
match manager.commit_transaction(session_id) {
Ok(()) => return Ok(()),
Err(Error::SerializationFailure(msg)) if attempt < max_retries - 1 => {
println!("Serialization conflict (attempt {}), retrying...", attempt + 1);
std::thread::sleep(std::time::Duration::from_millis(100 * (2_u64.pow(attempt))));
continue;
}
Err(e) => return Err(e),
}
}
Err(e) => {
manager.rollback_transaction(session_id)?;
return Err(e);
}
}
}
Err(Error::SerializationFailure("Max retries exceeded".to_string()))
}
fn perform_transfer(db: &EmbeddedDatabase, from_id: i32, to_id: i32, amount: i32) -> Result<(), Error> {
// Debit from account
db.execute(&format!(
"UPDATE accounts SET balance = balance - {} WHERE id = {}",
amount, from_id
))?;
// Credit to account
db.execute(&format!(
"UPDATE accounts SET balance = balance + {} WHERE id = {}",
amount, to_id
))?;
Ok(())
}
Example 3: Programmatic Dump/Restore¶
use heliosdb_lite::storage::dump::*;
use std::path::PathBuf;
fn backup_and_restore() -> Result<(), Error> {
let db = EmbeddedDatabase::new_in_memory()?;
let dump_manager = DumpManager::new(db.storage_engine());
// Create test data
db.execute("CREATE TABLE users (id INT PRIMARY KEY, name TEXT)")?;
db.execute("INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')")?;
// Dump database
let dump_opts = DumpOptions {
output_path: PathBuf::from("/tmp/backup.heliodump"),
mode: DumpMode::Full,
compress: true,
compression_type: CompressionType::Zstd,
tables: None,
append: false,
};
let dump_report = dump_manager.dump(dump_opts)?;
println!("Dump complete: {} rows, {} bytes",
dump_report.rows_dumped,
dump_report.bytes_written
);
// Verify dump
let valid = dump_manager.verify_dump(&PathBuf::from("/tmp/backup.heliodump"))?;
assert!(valid, "Dump verification failed");
// Create new database
let db2 = EmbeddedDatabase::new_in_memory()?;
let restore_manager = DumpManager::new(db2.storage_engine());
// Restore from dump
let restore_opts = RestoreOptions {
input_path: PathBuf::from("/tmp/backup.heliodump"),
tables: None,
mode: RestoreMode::Clean,
on_conflict: ConflictResolution::Error,
};
let restore_report = restore_manager.restore(restore_opts)?;
println!("Restore complete: {} tables, {} rows",
restore_report.tables_restored,
restore_report.rows_restored
);
// Verify data
let count: i64 = db2.query_one("SELECT COUNT(*) FROM users", &[])?;
assert_eq!(count, 2);
Ok(())
}
Thread Safety Guarantees¶
All session management APIs are thread-safe and can be safely shared across threads using Arc:
use std::sync::Arc;
let manager = Arc::new(SessionManager::new(config));
let lock_manager = Arc::new(LockManager::new(lock_config));
// Share across threads
let manager_clone = manager.clone();
std::thread::spawn(move || {
let session_id = manager_clone.create_session(&user, IsolationLevel::ReadCommitted).unwrap();
// ...
});
Internal Synchronization:
- SessionManager: Uses DashMap for lock-free concurrent access
- LockManager: Uses DashMap and atomic operations
- DumpManager: Uses read-write locks for safe concurrent dumps
- Transaction: Isolated per-session, no cross-session contention
Concurrency Patterns¶
Pattern 1: Connection Pool Integration¶
use r2d2::{Pool, PooledConnection};
use heliosdb_lite::EmbeddedDatabase;
type DbPool = Pool<EmbeddedDatabase>;
fn create_pool() -> Result<DbPool, Error> {
let db = EmbeddedDatabase::new_in_memory()?;
Ok(Pool::builder()
.max_size(20)
.build(db)?)
}
fn get_connection(pool: &DbPool) -> Result<PooledConnection<EmbeddedDatabase>, Error> {
pool.get().map_err(|e| Error::Other(e.to_string()))
}
Pattern 2: Async Session Management¶
use tokio::sync::Mutex;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Error> {
let manager = Arc::new(Mutex::new(SessionManager::new(config)));
let handles: Vec<_> = (0..100).map(|i| {
let manager = manager.clone();
tokio::spawn(async move {
let manager = manager.lock().await;
let user = User::new(format!("user{}", i), "pass");
manager.create_session(&user, IsolationLevel::ReadCommitted)
})
}).collect();
for handle in handles {
handle.await??;
}
Ok(())
}
Integration Examples¶
Integration with Web Framework (Axum)¶
use axum::{
extract::{State, Json},
routing::post,
Router,
};
use std::sync::Arc;
struct AppState {
db: Arc<EmbeddedDatabase>,
session_manager: Arc<SessionManager>,
}
async fn create_user(
State(state): State<Arc<AppState>>,
Json(payload): Json<CreateUserRequest>,
) -> Result<Json<CreateUserResponse>, AppError> {
let user = User::new("api_user", "secret");
let session_id = state.session_manager.create_session(
&user,
IsolationLevel::ReadCommitted
)?;
state.session_manager.begin_transaction(session_id)?;
state.db.execute(&format!(
"INSERT INTO users (name, email) VALUES ('{}', '{}')",
payload.name, payload.email
))?;
state.session_manager.commit_transaction(session_id)?;
state.session_manager.destroy_session(session_id)?;
Ok(Json(CreateUserResponse { success: true }))
}
#[tokio::main]
async fn main() {
let db = Arc::new(EmbeddedDatabase::new_in_memory().unwrap());
let session_manager = Arc::new(SessionManager::new(SessionConfig::default()));
let state = Arc::new(AppState { db, session_manager });
let app = Router::new()
.route("/users", post(create_user))
.with_state(state);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
See Also¶
- In-Memory Mode Guide - User guide for in-memory operations
- Configuration Reference - Configuration options
- Multi-User Architecture - System design details
- Migration Guide - Upgrading from v3.0
Version: 3.1.0 Last Updated: 2025-12-08 Maintained by: HeliosDB Team