rocksolid 3.0.0

An ergonomic, high-level RocksDB wrapper for Rust. Features CF-aware optimistic & pessimistic transactions, advanced routing for merge operators and compaction filters, performance tuning profiles, batching, TTL values, and DAO macros.
Documentation
// Tests for the DB-wide options hook (`custom_options_db`) on transactional stores,
// and the flush conveniences.

mod common;

use common::setup_logging;
use rocksolid::store::DefaultCFOperations;
use rocksolid::tx::cf_tx_store::{RocksDbCFTxnStore, RocksDbTransactionalStoreConfig, TransactionalEngine};
use rocksolid::tx::optimistic_tx_store::{RocksDbOptimisticTxnStore, RocksDbOptimisticTxnStoreConfig};
use rocksolid::CFOperations;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

#[test]
fn test_pessimistic_cf_txn_store_custom_options_db() {
  setup_logging();
  let temp_dir = tempfile::tempdir().unwrap();
  let db_path = temp_dir.path().join("pessimistic_custom_db_opts");

  let callback_ran = Arc::new(AtomicBool::new(false));
  let callback_ran_clone = callback_ran.clone();

  let config = RocksDbTransactionalStoreConfig {
    path: db_path.to_str().unwrap().to_string(),
    create_if_missing: true,
    column_families_to_open: vec![rocksdb::DEFAULT_COLUMN_FAMILY_NAME.to_string()],
    custom_options_db: Some(Box::new(move |db_opts| {
      db_opts.inner.set_max_total_wal_size(64 * 1024 * 1024);
      db_opts.inner.set_wal_ttl_seconds(60);
      callback_ran_clone.store(true, Ordering::SeqCst);
    })),
    engine: TransactionalEngine::Pessimistic(Default::default()),
    ..Default::default()
  };

  let store = RocksDbCFTxnStore::open(config).unwrap();
  assert!(
    callback_ran.load(Ordering::SeqCst),
    "custom_options_db must be invoked while building DB-wide options"
  );

  store
    .put(rocksdb::DEFAULT_COLUMN_FAMILY_NAME, "key1", &"value1".to_string())
    .unwrap();
  let read: Option<String> = store.get(rocksdb::DEFAULT_COLUMN_FAMILY_NAME, "key1").unwrap();
  assert_eq!(read, Some("value1".to_string()));
}

#[test]
fn test_optimistic_txn_store_custom_options_db() {
  setup_logging();
  let temp_dir = tempfile::tempdir().unwrap();
  let db_path = temp_dir.path().join("optimistic_custom_db_opts");

  let callback_ran = Arc::new(AtomicBool::new(false));
  let callback_ran_clone = callback_ran.clone();

  let config = RocksDbOptimisticTxnStoreConfig {
    path: db_path.to_str().unwrap().to_string(),
    create_if_missing: true,
    custom_options_db: Some(Box::new(move |db_opts| {
      db_opts.inner.set_max_total_wal_size(64 * 1024 * 1024);
      callback_ran_clone.store(true, Ordering::SeqCst);
    })),
    ..Default::default()
  };

  let store = RocksDbOptimisticTxnStore::open(config).unwrap();
  assert!(
    callback_ran.load(Ordering::SeqCst),
    "custom_options_db must be invoked while building DB-wide options"
  );

  store.put("key1", &"value1".to_string()).unwrap();
  let read: Option<String> = store.get("key1").unwrap();
  assert_eq!(read, Some("value1".to_string()));

  store.flush().unwrap();
  store.flush_wal(true).unwrap();
}

#[test]
fn test_tunable_wal_setters_lock() {
  use rocksolid::tuner::Tunable;

  let mut opts = Tunable::new(rocksdb::Options::default());
  opts.set_max_total_wal_size(128 * 1024 * 1024);
  opts.set_wal_ttl_seconds(300);
  opts.set_wal_size_limit_mb(512);
  opts.set_db_write_buffer_size(64 * 1024 * 1024);

  assert!(opts.is_locked("db_max_total_wal_size"));
  assert!(opts.is_locked("db_wal_ttl_seconds"));
  assert!(opts.is_locked("db_wal_size_limit_mb"));
  assert!(opts.is_locked("db_write_buffer_size"));

  // tune_ variants must be no-ops once locked (no way to read back; this
  // exercises the conditional path for coverage).
  opts.tune_set_max_total_wal_size(1);
  opts.tune_set_wal_ttl_seconds(1);
}