or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

core-database.mddocs/reference/

Core Database Operations

Database management including connection establishment, lifecycle management, and core database-level operations. The Database interface provides the primary entry point for creating transactions and managing database resources.

Capabilities

FDB Initialization

Initialize the FoundationDB API and manage network lifecycle. API version selection is required before using any FoundationDB operations.

/**
 * Select API version for the client.
 * Must be called before any other FoundationDB operations.
 * Can only be called once per JVM lifetime.
 *
 * Parameters:
 * - version: int - API version to select (e.g., 740 for version 7.4.0)
 *
 * Returns:
 * FDB - FoundationDB API singleton instance
 *
 * Throws:
 * IllegalArgumentException - If version not supported
 * FDBException - If version already selected with different value
 */
static FDB FDB.selectAPIVersion(int version);

/**
 * Get FDB API singleton instance.
 * Only available after selectAPIVersion() has been called.
 *
 * Returns:
 * FDB - FoundationDB API singleton instance
 *
 * Throws:
 * FDBException - If API version not yet selected
 */
static FDB FDB.instance();

/**
 * Check if API version has been selected.
 *
 * Returns:
 * boolean - true if selectAPIVersion() has been called successfully
 */
static boolean FDB.isAPIVersionSelected();

/**
 * Get the selected API version number.
 *
 * Returns:
 * int - Selected API version
 */
int FDB.getAPIVersion();

/**
 * Get network configuration options.
 * Options must be set before network starts (before first open() call).
 *
 * Returns:
 * NetworkOptions - Network configuration interface
 */
NetworkOptions FDB.options();

/**
 * Start network thread manually.
 * Normally called automatically by first open().
 * Can only be called once per JVM.
 */
void FDB.startNetwork();

/**
 * Start network thread with custom executor.
 *
 * Parameters:
 * - e: Executor - Executor for network operations
 */
void FDB.startNetwork(Executor e);

/**
 * Stop network thread.
 * Should only be called on application shutdown.
 * Network cannot be restarted after stopping.
 */
void FDB.stopNetwork();

/**
 * Disable automatic shutdown hook that stops network on JVM exit.
 * Use if you need custom shutdown logic.
 */
void FDB.disableShutdownHook();

/**
 * Enable or disable warnings for unclosed FoundationDB objects.
 * Default is true (warnings enabled).
 *
 * Parameters:
 * - warnOnUnclosed: boolean - Whether to warn on unclosed objects
 */
void FDB.setUnclosedWarning(boolean warnOnUnclosed);

/**
 * Enable or disable DirectByteBuffer usage for getRange() queries.
 * Can improve performance for large range reads.
 *
 * Parameters:
 * - enabled: boolean - Whether to use DirectByteBuffers
 */
void FDB.enableDirectBufferQuery(boolean enabled);

/**
 * Check if DirectByteBuffer queries are enabled.
 *
 * Returns:
 * boolean - true if DirectByteBuffers enabled for range queries
 */
boolean FDB.isDirectBufferQueriesEnabled();

/**
 * Resize DirectBufferPool used by getRange() requests.
 * Allows tuning pool size and buffer size for better performance.
 *
 * Parameters:
 * - poolSize: int - Number of buffers in pool
 * - bufferSize: int - Size of each buffer in bytes
 */
void FDB.resizeDirectBufferPool(int poolSize, int bufferSize);

/**
 * Create cluster connection (deprecated).
 * Use open() instead.
 *
 * Returns:
 * Cluster - Connection to default cluster
 *
 * @deprecated Use FDB.open() instead
 */
@Deprecated
Cluster FDB.createCluster();

/**
 * Create cluster connection with cluster file (deprecated).
 * Use open(String) instead.
 *
 * Parameters:
 * - clusterFilePath: String - Path to cluster file (null for default)
 *
 * Returns:
 * Cluster - Connection to specified cluster
 *
 * @deprecated Use FDB.open(String) instead
 */
@Deprecated
Cluster FDB.createCluster(String clusterFilePath);

/**
 * Create cluster connection with custom executor (deprecated).
 * Use open(String, Executor) instead.
 *
 * Parameters:
 * - clusterFilePath: String - Path to cluster file (null for default)
 * - e: Executor - Executor for async operations
 *
 * Returns:
 * Cluster - Connection to specified cluster
 *
 * @deprecated Use FDB.open(String, Executor) instead
 */
@Deprecated
Cluster FDB.createCluster(String clusterFilePath, Executor e);

/**
 * Default executor service for async operations.
 * Cached thread pool with daemon threads.
 */
static final ExecutorService FDB.DEFAULT_EXECUTOR;

Usage examples:

import com.apple.foundationdb.*;

public class FDBSetup {
    public static void main(String[] args) {
        // Required: Select API version first
        FDB fdb = FDB.selectAPIVersion(740);

        // Check if version is selected
        if (FDB.isAPIVersionSelected()) {
            System.out.println("API version: " + fdb.getAPIVersion());
        }

        // Get singleton instance (after selectAPIVersion)
        FDB fdb2 = FDB.instance(); // Same instance as fdb

        // Configure network options before starting
        fdb.options().setTraceEnable("/var/log/fdb-traces");
        fdb.options().setTLSCertPath("/etc/fdb/cert.pem");

        // Disable unclosed warnings if desired
        fdb.setUnclosedWarning(false);

        // Enable DirectByteBuffer for better performance
        fdb.enableDirectBufferQuery(true);

        // Network starts automatically on first open()
        try (Database db = fdb.open()) {
            // Use database...
        }

        // Stop network on shutdown (usually done automatically)
        // fdb.stopNetwork();
    }
}

// Manual network control
public class ManualNetworkControl {
    public static void main(String[] args) {
        FDB fdb = FDB.selectAPIVersion(740);

        // Start network manually
        fdb.startNetwork();

        // Or with custom executor
        Executor networkExecutor = Executors.newFixedThreadPool(4);
        // fdb.startNetwork(networkExecutor);

        try (Database db = fdb.open()) {
            // Use database...
        }

        // Stop network manually
        fdb.stopNetwork();
    }
}

Database Connection

Open and manage connections to FoundationDB clusters.

/**
 * Open database connection to default cluster.
 * Network starts automatically if not already running.
 * 
 * Returns:
 * Database - Connection to FoundationDB cluster
 */
Database FDB.open();

/**
 * Open database connection using specified cluster file.
 * 
 * Parameters:
 * - clusterFilePath: String - Path to fdb.cluster file, or null for default
 * 
 * Returns:
 * Database - Connection to FoundationDB cluster
 */
Database FDB.open(String clusterFilePath);

/**
 * Open database connection with event tracking.
 *
 * Parameters:
 * - clusterFilePath: String - Path to fdb.cluster file, or null for default
 * - eventKeeper: EventKeeper - Instrumentation for tracking FDB operations
 *
 * Returns:
 * Database - Connection to FoundationDB cluster
 */
Database FDB.open(String clusterFilePath, EventKeeper eventKeeper);

/**
 * Open database connection with custom executor for async callbacks.
 *
 * Parameters:
 * - clusterFilePath: String - Path to fdb.cluster file, or null for default
 * - e: Executor - Executor for asynchronous callback execution
 *
 * Returns:
 * Database - Connection to FoundationDB cluster
 */
Database FDB.open(String clusterFilePath, Executor e);

/**
 * Open database connection with custom executor and event tracking.
 *
 * Parameters:
 * - clusterFilePath: String - Path to fdb.cluster file, or null for default
 * - e: Executor - Executor for asynchronous callback execution
 * - eventKeeper: EventKeeper - Instrumentation for tracking FDB operations
 *
 * Returns:
 * Database - Connection to FoundationDB cluster
 */
Database FDB.open(String clusterFilePath, Executor e, EventKeeper eventKeeper);

Usage example:

import com.apple.foundationdb.*;

public class DatabaseExample {
    public static void main(String[] args) {
        FDB fdb = FDB.selectAPIVersion(740);
        
        // Simple connection to default cluster
        try (Database db = fdb.open()) {
            // Use database...
        }
        
        // Connection with custom cluster file
        try (Database db = fdb.open("/etc/foundationdb/fdb.cluster")) {
            // Use database...
        }
        
        // Connection with custom executor
        Executor customExecutor = Executors.newFixedThreadPool(10);
        try (Database db = fdb.open(null, customExecutor)) {
            // Async callbacks run on customExecutor
        }
    }
}

Transaction Creation

Create transaction objects for manual lifecycle management.

/**
 * Create a new transaction on this database.
 * Uses database's default executor for async operations.
 * 
 * Returns:
 * Transaction - New transaction object (must be closed after use)
 */
Transaction Database.createTransaction();

/**
 * Create a new transaction with custom executor.
 * 
 * Parameters:
 * - e: Executor - Executor for asynchronous callback execution
 * 
 * Returns:
 * Transaction - New transaction object (must be closed after use)
 */
Transaction Database.createTransaction(Executor e);

/**
 * Create a new transaction with custom executor and event tracking.
 * 
 * Parameters:
 * - e: Executor - Executor for asynchronous callback execution
 * - eventKeeper: EventKeeper - Instrumentation for tracking transaction operations
 * 
 * Returns:
 * Transaction - New transaction object (must be closed after use)
 */
Transaction Database.createTransaction(Executor e, EventKeeper eventKeeper);

Usage example:

// Manual transaction management
try (Transaction tr = db.createTransaction()) {
    tr.set("key".getBytes(), "value".getBytes());
    tr.commit().join();
} catch (FDBException e) {
    // Handle errors - manual retry required
}

Database Status and Monitoring

Query database health and performance metrics.

/**
 * Get main thread busyness metric indicating client saturation.
 * Value of 0 indicates idle, 1.0+ indicates saturation.
 * 
 * Returns:
 * double - Busyness metric (0.0 = idle, 1.0+ = saturated)
 */
double Database.getMainThreadBusyness();

/**
 * Get comprehensive client status information as JSON using default executor.
 *
 * Returns:
 * CompletableFuture<byte[]> - JSON-encoded client status
 */
CompletableFuture<byte[]> Database.getClientStatus();

/**
 * Get comprehensive client status information as JSON.
 *
 * Parameters:
 * - e: Executor - Executor for asynchronous operation
 *
 * Returns:
 * CompletableFuture<byte[]> - JSON-encoded client status
 */
CompletableFuture<byte[]> Database.getClientStatus(Executor e);

Usage example:

// Check if client is saturated
double busyness = db.getMainThreadBusyness();
if (busyness > 0.8) {
    System.out.println("Warning: Client is heavily loaded");
}

// Get detailed status
CompletableFuture<byte[]> statusFuture = db.getClientStatus(db.getExecutor());
statusFuture.thenAccept(statusJson -> {
    String status = new String(statusJson);
    System.out.println("Client status: " + status);
});

Blob Granule Management

Manage blob granule storage for large datasets offloaded to blob storage.

/**
 * Mark a range for blobbification (moving to blob storage).
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Boolean> - True if operation succeeded
 */
CompletableFuture<Boolean> Database.blobbifyRange(byte[] beginKey, byte[] endKey, Executor e);

/**
 * Mark a range for blobbification, blocking until complete.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Boolean> - True if operation succeeded
 */
CompletableFuture<Boolean> Database.blobbifyRangeBlocking(
    byte[] beginKey, byte[] endKey, Executor e
);

/**
 * Remove blobbification from a range, returning data to normal storage.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Boolean> - True if operation succeeded
 */
CompletableFuture<Boolean> Database.unblobbifyRange(byte[] beginKey, byte[] endKey, Executor e);

/**
 * List all blobbified ranges within specified bounds.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of query range (inclusive)
 * - endKey: byte[] - End of query range (exclusive)
 * - rangeLimit: int - Maximum number of ranges to return
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<KeyRangeArrayResult> - Array of blobbified ranges
 */
CompletableFuture<KeyRangeArrayResult> Database.listBlobbifiedRanges(
    byte[] beginKey, byte[] endKey, int rangeLimit, Executor e
);

/**
 * Verify blob range integrity at specified version.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - version: long - Database version to verify at (-1 for latest)
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Long> - Version verified, or error code
 */
CompletableFuture<Long> Database.verifyBlobRange(
    byte[] beginKey, byte[] endKey, long version, Executor e
);

/**
 * Force flush of blob range to blob storage.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - compact: boolean - Whether to compact after flushing
 * - version: long - Database version to flush to (-1 for latest)
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Boolean> - True if flush succeeded
 */
CompletableFuture<Boolean> Database.flushBlobRange(
    byte[] beginKey, byte[] endKey, boolean compact, long version, Executor e
);

/**
 * Purge blob granules for specified range up to given version.
 * 
 * Parameters:
 * - beginKey: byte[] - Start of range (inclusive)
 * - endKey: byte[] - End of range (exclusive)
 * - purgeVersion: long - Version up to which to purge
 * - force: boolean - Force purge even if data might be needed
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<byte[]> - Purge key for tracking completion
 */
CompletableFuture<byte[]> Database.purgeBlobGranules(
    byte[] beginKey, byte[] endKey, long purgeVersion, boolean force, Executor e
);

/**
 * Wait for purge operation to complete.
 * 
 * Parameters:
 * - purgeKey: byte[] - Key returned from purgeBlobGranules
 * - e: Executor - Executor for asynchronous operation
 * 
 * Returns:
 * CompletableFuture<Void> - Completes when purge is done
 */
CompletableFuture<Void> Database.waitPurgeGranulesComplete(byte[] purgeKey, Executor e);

Usage example:

// Blobbify a range for long-term storage
byte[] rangeStart = "archive/2020".getBytes();
byte[] rangeEnd = "archive/2021".getBytes();

db.blobbifyRange(rangeStart, rangeEnd, db.getExecutor())
    .thenAccept(success -> {
        if (success) {
            System.out.println("Range successfully blobbified");
        }
    });

// List all blobbified ranges
db.listBlobbifiedRanges(new byte[0], new byte[]{(byte)0xFF}, 100, db.getExecutor())
    .thenAccept(result -> {
        for (Range range : result.getRanges()) {
            System.out.println("Blobbified: " + range);
        }
    });

Resource Management

/**
 * Get the executor used for asynchronous callbacks.
 * 
 * Returns:
 * Executor - Executor for async operations
 */
Executor Database.getExecutor();

/**
 * Close database connection and release all resources.
 * Must be called when database is no longer needed.
 * Transactions created from this database should be closed first.
 */
void Database.close();

Usage example:

// Proper resource management with try-with-resources
try (Database db = fdb.open()) {
    // Use database
    db.run(tr -> {
        // Transaction operations
        return null;
    });
} // Database automatically closed

// Manual resource management
Database db = fdb.open();
try {
    // Use database
} finally {
    db.close();
}

Database Options

Access configuration options for database-level behavior.

/**
 * Get options interface for configuring database behavior.
 * Options must be set before they take effect.
 * 
 * Returns:
 * DatabaseOptions - Options configuration interface
 */
DatabaseOptions Database.options();

See Configuration Options for detailed options documentation.

Types

interface Database extends AutoCloseable, TransactionContext {
    // All methods documented above
}

interface TransactionContext extends ReadTransactionContext {
    <T> T run(Function<? super Transaction, T> retryable);
    <T> CompletableFuture<T> runAsync(
        Function<? super Transaction, ? extends CompletableFuture<T>> retryable
    );
}

interface ReadTransactionContext {
    <T> T read(Function<? super ReadTransaction, T> retryable);
    <T> CompletableFuture<T> readAsync(
        Function<? super ReadTransaction, ? extends CompletableFuture<T>> retryable
    );
    Executor getExecutor();
}

class KeyRangeArrayResult {
    Range[] getRanges();
}

Important Notes

Connection Management

  • Database connections are lightweight and can be long-lived
  • Reuse Database objects across your application
  • Network thread starts automatically on first open()
  • Only one network thread per JVM process

Resource Lifecycle

  • Always close Database objects when done
  • Use try-with-resources for automatic cleanup
  • Closing database does not stop network thread
  • Call FDB.stopNetwork() only on application shutdown

Executor Usage

  • Default executor is FDB.DEFAULT_EXECUTOR (daemon thread pool)
  • Custom executors enable control over thread pools
  • Async callbacks run on specified executor
  • Executor should not be shut down while database is active

Blob Granule Operations

  • Blob granules offload cold data to object storage
  • Blobbification is asynchronous and may take time
  • Verify operations ensure data integrity
  • Purge operations free blob storage space
  • Force flag on purge should be used with caution