Skip to content

Latest commit

 

History

History
364 lines (250 loc) · 12.8 KB

cookbook.md

File metadata and controls

364 lines (250 loc) · 12.8 KB

RustDB cookbook

Hands-on examples for the GitHub Container Registry image ghcr.io/crosseyedcat/rustdb. Commands below match the current CLI and packaged config.toml; re-verify after upgrading images (see Verification).

This cookbook focuses on:

  • Running RustDB from Docker with persistent data
  • Using the CLI (info, create, query, server)
  • Understanding configuration and the most useful env vars
  • Common workflows (batch SQL, QUIC server, smoke scripts, benchmarks)
  • Using RustDB embedded / in-process (library API) for tests and tools

For a browser-based try-it flow without Docker, see the interactive sandbox: sandbox.md (GitHub Codespaces).

Image and tags

CI publishes several tag styles (see .github/workflows/ci-cd.yml and docker/metadata-action):

Tag / pattern Purpose
latest Default branch when enabled by metadata
main, develop Branch builds
sha-<short> Short Git SHA (reproducible alongside branch tags)
pr-<n> Pull-request pipelines

For bit-for-bit reproducibility, pin by digest from the package page:

export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb:main"
docker pull "$RUSTDB_IMAGE"
# Optional: export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb@sha256:<digest>"

Note: the binary in the image may lag behind main in Git. Always check rustdb server --help and /app/config/config.toml inside the container. For QUIC framing, TLS leaf export, and clients, see docs/network/README.md.


1. Version

docker run --rm "$RUSTDB_IMAGE" rustdb --version

Expected: rustdb 0.1.0 (or the version in the image’s Cargo.toml).


2. System information

docker run --rm "$RUSTDB_IMAGE" rustdb info

Prints version, default language, OS, and architecture inside the container (typically linux / x86_64 or aarch64).


3. Interface language (i18n)

docker run --rm "$RUSTDB_IMAGE" rustdb language list
docker run --rm "$RUSTDB_IMAGE" rustdb language show
docker run --rm "$RUSTDB_IMAGE" rustdb language set en

4. SQL via CLI (query)

rustdb query runs SQL locally through SqlEngine (same parse → plan → execute path as the QUIC server), using the configured data directory.

docker run --rm "$RUSTDB_IMAGE" rustdb query "SELECT 1"
docker run --rm "$RUSTDB_IMAGE" rustdb query "SELECT 1" -d mydb

The second form uses -d / --database to resolve data under data_directory from config (default ./data, i.e. /app/data when using the image layout).

Query plans (EXPLAIN)

Inspect the planner/optimizer tree without changing the wire protocol:

docker run --rm "$RUSTDB_IMAGE" rustdb query "EXPLAIN SELECT 1"
docker run --rm "$RUSTDB_IMAGE" rustdb query "EXPLAIN ANALYZE INSERT INTO t (a) VALUES (1)"

See docs/sql-explain.md for syntax, supported statements, and DML caveats.

Batch mode (single session, multi-statement)

Use --batch-file to run one statement per line in a single process, using one SessionContext. This is required if you want to test transactions (BEGIN/COMMIT/ROLLBACK) across multiple statements.

Auto-commit note: if you run DML outside an explicit BEGIN … COMMIT, RustDB executes each DML statement as an implicit short transaction (auto-commit). That means standalone INSERT/UPDATE/DELETE statements are WAL-logged and committed at statement end (subject to the selected durability mode; see docs/durability-and-recovery.md).

Example via stdin (--batch-file -):

docker run --rm -i \
  -v rustdb-data:/app/data \
  "$RUSTDB_IMAGE" \
  sh -c 'rustdb --config /app/config/config.toml query --batch-file -' <<'SQL'
BEGIN TRANSACTION
INSERT INTO demo_t (a) VALUES (1)
ROLLBACK
SQL

Coverage of SQL features is still growing; see README.md for project status and test limitations.


Embedded / in-process (library API)

For tests, local tooling, or embedding RustDB inside another Rust process, you can use SqlEngine directly (no QUIC server). This is the same execution pipeline used by rustdb query.

Minimal example

use rustdb::network::engine::{EngineHandle, SessionContext};
use rustdb::network::sql_engine::SqlEngine;

let data_dir = std::path::PathBuf::from("./data/embedded-demo");
let engine = SqlEngine::open(data_dir).unwrap();

let mut ctx = SessionContext::default();
engine.execute_sql("CREATE TABLE t (a INTEGER)", &mut ctx).unwrap();
engine.execute_sql("INSERT INTO t (a) VALUES (1)", &mut ctx).unwrap();
let out = engine.execute_sql("SELECT a FROM t", &mut ctx).unwrap();
println!("{out:?}");

Crash/reopen testing pattern (durability)

To simulate a process crash in tests, close the engine (drop it) and reopen it on the same data directory. With WAL enabled (default), the invariants in docs/durability-and-recovery.md should hold after open().

use rustdb::network::engine::{EngineHandle, SessionContext};
use rustdb::network::sql_engine::SqlEngine;

let dir = tempfile::TempDir::new().unwrap();
let data_dir = dir.path().to_path_buf();

// Setup schema.
{
    let engine = SqlEngine::open(data_dir.clone()).unwrap();
    let mut ctx = SessionContext::default();
    engine.execute_sql("CREATE TABLE t (a INTEGER)", &mut ctx).unwrap();
}

// Simulate: BEGIN; INSERT; <crash>
{
    let engine = SqlEngine::open(data_dir.clone()).unwrap();
    let mut ctx = SessionContext::default();
    engine.execute_sql("BEGIN TRANSACTION", &mut ctx).unwrap();
    engine.execute_sql("INSERT INTO t (a) VALUES (1)", &mut ctx).unwrap();
    drop(ctx); // no COMMIT/ROLLBACK
}

// Reopen: WAL replay should undo the uncommitted insert.
{
    let engine = SqlEngine::open(data_dir.clone()).unwrap();
    let mut ctx = SessionContext::default();
    let out = engine.execute_sql("SELECT a FROM t", &mut ctx).unwrap();
    println!("{out:?}");
}

Local embedded tooling helpers

This repository also contains a small standalone binary, rustdb_tool, intended for quick health checks and WAL diagnostics for a data directory:

cargo run --bin rustdb_tool -- health --data-dir ./data/mydb
cargo run --bin rustdb_tool -- wal-status --data-dir ./data/mydb
cargo run --bin rustdb_tool -- checkpoint --data-dir ./data/mydb

5. Create a database directory (create)

rustdb create creates a directory for a named database and writes a small .rustdb marker file. It does not register a full catalog entry everywhere in the stack—treat it as a filesystem helper.

docker run --rm "$RUSTDB_IMAGE" rustdb create demo --data-dir /app/data

Ephemeral containers lose /app/data unless you mount a volume (next sections).


6. Server in the background (QUIC / UDP)

The network entrypoint is QUIC over UDP with ALPN rustdb-v1. Map ports with /udp.

The image ships config.toml at /app/config/config.toml with network.port = 5432. Recommended invocation:

docker rm -f rustdb-server 2>/dev/null || true
docker run -d --name rustdb-server \
  -p 15432:5432/udp \
  -v rustdb-data:/app/data \
  "$RUSTDB_IMAGE" \
  rustdb --config /app/config/config.toml server --host 0.0.0.0 --cert-out /tmp/server.der
  • --host 0.0.0.0 is required for connections from the host or other containers.
  • --cert-out writes the dev TLS leaf (DER) for rustdb_quic_client --cert (copy out with docker cp if needed).

Stop:

docker stop rustdb-server && docker rm rustdb-server

Dockerfile still EXPOSEs 8080/8081 for historical layout; the QUIC listener port comes from config or --port. To use another port: --port 8080 and -p 18080:8080/udp.


7. Data and config on disk

Example: named volume for data and a read-only host config (paths follow the Dockerfile):

docker run --rm \
  -v rustdb-data:/app/data \
  -v "$(pwd)/config.toml:/app/config/config.toml:ro" \
  "$RUSTDB_IMAGE" \
  rustdb --config /app/config/config.toml info

Config keys (practical reference)

The container expects a config file like /app/config/config.toml (see repository config.toml). The most used keys in the current image:

  • data_directory: base directory for database storage (in the image: /app/data)
  • language: interface language (e.g. en)
  • network.host / network.port: QUIC/UDP listener bind address and port

Environment variables (common)

RustDB reads a small set of env vars used in different parts of the stack:

  • RUST_LOG: logging filter for tracing-subscriber (server)
  • RUSTDB_TRACE_CHROME_PATH: when set, enables tracing-chrome JSON trace output (server)
  • RUSTDB_NAME, RUSTDB_DATA_DIR, RUSTDB_MAX_CONNECTIONS, RUSTDB_LANGUAGE: config overrides used by DatabaseConfig::from_env() (CLI / config helpers)

Example:

docker run --rm \
  -e RUST_LOG=info \
  -e RUSTDB_TRACE_CHROME_PATH=/app/logs/trace.json \
  -v rustdb-data:/app/data \
  "$RUSTDB_IMAGE" \
  rustdb --config /app/config/config.toml info

8. QUIC client (build from this repository)

The GHCR image contains only the rustdb binary. Build rustdb_quic_client (and optionally rustdb_load) from source:

git clone https://github.com/CrossEyedCat/RustDB.git && cd RustDB
cargo build --release --bin rustdb_quic_client

Then follow docs/network/README.md: run rustdb server, pass --cert / --server-name, and use --addr for host:port.


Verification

The repository script re-runs the main checks against an image (default ghcr.io/crosseyedcat/rustdb:main):

./scripts/verify-cookbook-docker.sh
# or: RUSTDB_IMAGE=ghcr.io/crosseyedcat/rustdb:sha-abc1234 ./scripts/verify-cookbook-docker.sh

Benchmark via GHCR (QUIC + SQLite comparison)

scripts/bench_via_ghcr_image.sh pulls the image, uses a data volume, warms up bench_t, starts rustdb server with --cert-out, copies the leaf cert to the host, and runs scripts/bench_sqlite_vs_rustdb.py.

export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb:main"
./scripts/bench_via_ghcr_image.sh

By default this script runs the server on UDP port 8080 inside the container (UDP_PORT on the host maps to 8080/udp). That differs from the packaged /app/config/config.toml default (5432) but matches the script’s expectations; set UDP_PORT if you need a different host port.

On Windows with Docker Desktop, you can use the PowerShell helper:

$env:RUSTDB_IMAGE = "ghcr.io/crosseyedcat/rustdb:main"
.\scripts\bench_via_ghcr_image.ps1

Or Git Bash: "C:\Program Files\Git\bin\bash.exe" -lc './scripts/bench_via_ghcr_image.sh'.

Optional: set POSTGRES_DSN for Postgres rows in the report. Output defaults under target/bench_docker_ghcr/ (or OUT_DIR if set).


Profiling image (optional)

The Dockerfile defines a profiler stage (Linux perf + cargo flamegraph). Example:

docker build -t rustdb-prof --target profiler .
# See comments in Dockerfile for run invocation

For CI-style flame graphs and tracing, see CONTRIBUTING.md (workflow_dispatch jobs).


docker-compose.yml in this repo

docker-compose.yml is an illustrative stack (Redis, Prometheus, Grafana, etc.). Comments mentioning HTTP/gRPC ports do not match the current QUIC/UDP server. For a minimal RustDB setup, prefer the docker run examples above and override the service command to rustdb --config /app/config/config.toml server ... with UDP port mappings if you adapt Compose.


See also


CLI quick reference

Run --help inside the container to confirm flags for the image you pinned:

docker run --rm "$RUSTDB_IMAGE" rustdb --help
docker run --rm "$RUSTDB_IMAGE" rustdb query --help
docker run --rm "$RUSTDB_IMAGE" rustdb server --help

Common commands:

  • rustdb info: prints system info
  • rustdb create <name>: creates a database directory (filesystem helper)
  • rustdb query <SQL>: runs one statement
  • rustdb query --batch-file <path|->: runs one statement per line (transactions span lines)
  • rustdb server: starts the QUIC/UDP server