voltdb-client-rust 0.1.12

A socket client library for Voltdb server
Documentation
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build & Test Commands

```bash
# Build
cargo build                    # Debug build (sync only)
cargo build --features tokio   # Build with async Tokio support
cargo build --release          # Release build

# Test (requires VoltDB Docker container running)
cargo test --verbose           # Run all tests
cargo test --features tokio    # Run tests including async tests

# Start VoltDB test container (required for tests)
docker run -d -p 21212:21212 -p 21211:21211 basvanbeek/voltdb-community:9.2.1

# Other commands
cargo check                    # Type check without building
cargo fix                      # Auto-fix lint warnings
```

## Architecture Overview

This is a pure Rust socket client library for VoltDB (in-memory distributed SQL database).

### Core Components

**Connection Layer (Sync):**
- `node.rs` - Single TCP connection wrapper. Spawns background listener thread for async message reception. Uses handle-based request tracking with mpsc channels.
- `pool.rs` - Connection pool (default 10 connections) with round-robin load balancing via atomic counter.

**Connection Layer (Async - requires `tokio` feature):**
- `async_node.rs` - Async Node using `tokio::net::TcpStream`. Uses `tokio::spawn` for background reader, `tokio::sync::mpsc` for channels.
- `async_pool.rs` - Async Pool with `Arc<AsyncNode>` connections for concurrent access.

**Protocol Layer:**
- `procedure_invocation.rs` - Encodes procedure calls into VoltDB binary protocol format
- `response.rs` - Parses server responses, handles status codes and metadata
- `encode.rs` / `encode_option.rs` - Type marshalling/unmarshalling via `Value` trait. All serializable types implement `get_write_length()`, `marshal()`, `marshal_in_table()`, `from_bytes()`.

**Data Layer:**
- `table.rs` - `VoltTable` struct for result sets. Supports column metadata, row iteration (`advance_row()`), and value fetching.

### Communication Flow

```
pool.get_conn() → node.query()/call_sp() → ProcedureInvocation::bytes()
    → TcpStream → [Background Thread] → mpsc channel → block_for_result()
```

Request-response matching uses unique i64 handles for async routing.

### Key API Patterns

**Sync API:**
```rust
// Connection pooling
let pool = Pool::new(opts)?;
let conn = pool.get_conn()?;

// Query execution
let table = conn.query("SELECT * FROM foo")?;
while table.advance_row() {
    let val: i32 = table.get_i32_by_column("col")?;
}

// Stored procedure with params
use voltdb_client_rust::volt_param;
let params = volt_param![1i32, "test".to_string()];
let table = conn.call_sp("MyProcedure", params)?;
```

**Async API (with `tokio` feature):**
```rust
// Cargo.toml: voltdb-client-rust = { version = "0.1.12", features = ["tokio"] }
use voltdb_client_rust::{AsyncPool, Opts, IpPort};

let hosts = vec![IpPort::new("localhost".to_string(), 21211)];
let pool = AsyncPool::new(Opts::new(hosts)).await?;
let conn = pool.get_conn();

let table = conn.query("SELECT * FROM foo").await?;
while table.advance_row() {
    let val: i32 = table.get_i32_by_column("col")?;
}
```

### Type Mapping

VoltDB types map to: i8/i16/i32/i64 (and unsigned), f64, BigDecimal, String, Vec<u8>, DateTime<Utc>, VoltTable. All support `Option<T>` for NULL values.

## Testing Notes

Integration tests in `tests/` require a running VoltDB instance. Tests use `testcontainers` crate to manage Docker containers automatically when possible.