Skip to content

Session Management API Documentation

Version: 3.1.0 Status: Production-Ready Last Updated: 2025-12-08

Table of Contents

  1. Overview
  2. SessionManager API
  3. LockManager API
  4. Transaction API Updates
  5. DumpManager API
  6. Type Definitions
  7. Error Types
  8. Code Examples
  9. Thread Safety Guarantees
  10. Concurrency Patterns
  11. 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

use heliosdb_lite::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) -> Self

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:

pub fn create_session(
    &self,
    user: &User,
    isolation: IsolationLevel
) -> Result<SessionId, Error>

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:

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 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:

pub fn commit_transaction(&self, session_id: SessionId) -> Result<(), Error>

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:

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_lite::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 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:

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_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

use heliosdb_lite::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_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:

pub fn restore(&self, options: RestoreOptions) -> Result<RestoreReport, Error>

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

#[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_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


Version: 3.1.0 Last Updated: 2025-12-08 Maintained by: HeliosDB Team