elips/docs
C++ API

C++ Transactions

ELIPS supports atomic, multi-vault transaction write batching via elips::Transaction and elips::TransactionVault.

Overview

Transactions guarantee Atomicity, Consistency, Isolation, and Durability (ACID) for write operations across multiple vaults. Either all vector insertions and erasures are committed to disk and memory atomically, or none are applied.

Transaction Class

cpp
class Transaction {
public:
    explicit Transaction(ElipsInstance& db);
    ~Transaction(); // Automatically rolls back if commit() was not called

    TransactionVault vault(const std::string& name);
    void commit();
    void rollback() noexcept;
};

TransactionVault Class

cpp
class TransactionVault {
public:
    RecordID place(
        const Vector& vector,
        Payload payload = {},
        std::optional<RecordID> id = std::nullopt
    );
    void erase(const RecordID& id);
};

Two-Phase Write Protocol

When txn.commit() is invoked:

  1. Validation Phase: The transaction checks vault write permissions, validates vector dimensions, and prepares undo records.
  2. WAL Logging: All batched operations are written to the Write-Ahead Log (WAL) with a transaction sequence marker.
  3. Memory Application: Vectors are inserted into HNSW indices and payload stores across target vaults.
  4. Rollback Recovery: If any stage fails (e.g. disk write failure), all in-memory changes are rolled back using internal undo buffers.

RAII & Exception Safety

Transaction follows RAII. If a Transaction goes out of scope before commit() completes successfully, its destructor automatically triggers rollback().

Complete Code Example

cpp
#include <elips/elips.hpp>
#include <iostream>

void atomic_transfer(elips::ElipsInstance& db) {
    // Begin transaction handle
    auto txn = db.begin_transaction();

    try {
        // Enqueue operations across multiple vaults
        auto users = txn.vault("users");
        auto logs = txn.vault("logs");

        elips::Vector user_vec = {0.1f, 0.2f, 0.3f, 0.4f};
        elips::Vector log_vec = {0.9f, 0.8f, 0.7f, 0.6f};

        users.place(user_vec, {{"user_id", std::string("u_100")}});
        logs.place(log_vec, {{"action", std::string("user_created")}});

        // Commit atomically
        txn.commit();
        std::cout << "Transaction committed successfully!" << std::endl;
    } catch (const elips::ElipsException& ex) {
        std::cerr << "Transaction failed: " << ex.what() << std::endl;
        txn.rollback();
    }
}