Session Management API Documentation
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 Nano 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_nano::├── 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 interfaceMinimum Rust Version: 1.75+
SessionManager API
Module
use heliosdb_nano::session::{SessionManager, Session, SessionId, IsolationLevel};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:
pub fn new(config: SessionConfig) -> SelfParameters:
config:SessionConfig- Configuration for session management
Example:
use heliosdb_nano::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:
pub fn create_session( &self, user: &User, isolation: IsolationLevel) -> Result<SessionId, Error>Parameters:
user:&User- User credentials and metadataisolation:IsolationLevel- Transaction isolation level
Returns: Result<SessionId, Error>
Errors:
Error::AuthenticationFailed- User authentication failedError::QuotaExceeded- Session limit exceeded for user
Example:
use heliosdb_nano::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:
pub fn begin_transaction(&self, session_id: SessionId) -> Result<TransactionId, Error>Parameters:
session_id:SessionId- Active session identifier
Returns: Result<TransactionId, Error>
Errors:
Error::SessionNotFound- Invalid session IDError::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:
pub fn commit_transaction(&self, session_id: SessionId) -> Result<(), Error>Errors:
Error::NoActiveTransaction- No transaction to commitError::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:
pub fn list_active_sessions(&self) -> Vec<SessionId>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
use heliosdb_nano::storage::{LockManager, LockMode, Key};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:
S X U S ✓ ✗ ✓ X ✗ ✗ ✗ U ✓ ✗ ✗Methods
acquire_lock
Acquire a lock on a key with specified mode.
Signature:
pub fn acquire_lock( &self, txn_id: TransactionId, key: Key, mode: LockMode) -> Result<(), Error>Parameters:
txn_id:TransactionId- Transaction acquiring lockkey:Key- Resource to lock (table, row, page)mode:LockMode- Lock type
Errors:
Error::LockTimeout- Timeout waiting for lockError::Deadlock- Deadlock detected
Example:
use heliosdb_nano::storage::{LockManager, LockMode, Key};
let lock_manager = LockManager::new(LockConfig::default());
// Acquire shared lock for readlet key = Key::row("users", 123);lock_manager.acquire_lock(txn_id, key.clone(), LockMode::Shared)?;
// Read data...
// Upgrade to exclusive lock for writelock_manager.acquire_lock(txn_id, key.clone(), LockMode::Exclusive)?;
// Write data...
// Release lockslock_manager.release_all_locks(txn_id)?;detect_deadlock
Check if transaction is involved in a deadlock.
Signature:
pub fn detect_deadlock(&self, txn_id: TransactionId) -> Result<bool, Error>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_nano::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_nano::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
use heliosdb_nano::storage::dump::{DumpManager, DumpOptions, RestoreOptions};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:
pub fn dump(&self, options: DumpOptions) -> Result<DumpReport, Error>Example:
use heliosdb_nano::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:
pub fn restore(&self, options: RestoreOptions) -> Result<RestoreReport, Error>Example:
use heliosdb_nano::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
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]pub struct UserId(u64);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
pub type Result<T> = std::result::Result<T, Error>;Code Examples
Example 1: Multi-User Application
use heliosdb_nano::{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_nano::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_nano::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 threadslet manager_clone = manager.clone();std::thread::spawn(move || { let session_id = manager_clone.create_session(&user, IsolationLevel::ReadCommitted).unwrap(); // ...});Internal Synchronization:
SessionManager: UsesDashMapfor lock-free concurrent accessLockManager: UsesDashMapand atomic operationsDumpManager: Uses read-write locks for safe concurrent dumpsTransaction: Isolated per-session, no cross-session contention
Concurrency Patterns
Pattern 1: Connection Pool Integration
use r2d2::{Pool, PooledConnection};use heliosdb_nano::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