dbkit-rs 0.1.1

Reusable Postgres + DuckDB database infrastructure: connection pooling, caching, batch operations, and migrations
Documentation

dbkit-rs

Reusable Postgres + DuckDB database infrastructure for Rust applications.

Features

  • Connection poolingConnectionManager wraps deadpool-postgres with auto-create database, configurable pool size, and timeouts
  • ConfigurableDbkitConfig builder with connection string construction, SSL modes, and pool tuning
  • Unified query executorBaseHandler for Postgres writes (WriteOp) and optional DuckDB analytical reads (ReadOp)
  • Migration trackingInitializationHandler with named migrations tracked by content hash
  • Concurrent cache — DashMap-based key-value cache with named buckets
  • Optional DuckDB — behind a duckdb feature flag to avoid the heavy bundled build when not needed

Usage

use dbkit::{ConnectionManager, DbkitConfig, BaseHandler, InitializationHandler};
use std::sync::Arc;

// Connect with defaults
let conn = ConnectionManager::new("postgres://localhost/myapp").await?;

// Or use the config builder
let config = DbkitConfig::builder()
    .host("localhost")
    .database("myapp")
    .user("admin")
    .password("secret")
    .pool_size(32)
    .build();
let conn = ConnectionManager::connect(config).await?;

let pool = Arc::new(conn.pool().clone());

// Run tracked migrations
let init = InitializationHandler::new(pool.clone());
init.run_named_migration("001_users", "
    CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        name TEXT NOT NULL
    )
").await?;

// Query
let handler = BaseHandler::new(pool);

Pool health

let status = conn.pool_status();
println!("connections: {}/{}", status.size, status.max_size);
println!("available: {}, waiting: {}", status.available, status.waiting);

DuckDB reads (optional)

Enable the duckdb feature:

dbkit = { version = "0.1", features = ["duckdb"] }
use dbkit::{BaseHandler, ReadOp, DuckParam, FetchMode};

let handler = BaseHandler::with_duckdb(pool, "postgres://localhost/myapp")?;

let result = handler.execute_read(ReadOp::Standard {
    query: "SELECT name FROM users WHERE id = $1",
    params: vec![DuckParam::Int(1)],
    map_fn: |row| Ok(row.get::<_, String>(0)?),
    mode: FetchMode::One,
}).await?;

Cache

use dbkit::Cache;

let cache = Cache::with_buckets(&["products", "prices"]);
cache.set("products", "abc123", "Widget".to_string());
let val = cache.get("products", "abc123");

Feature flags

Feature Default Description
duckdb off Enables DuckDB analytical reads via BaseHandler::with_duckdb()

License

MIT