VeltrixDB Docs
v1.1.0 GitHub FAQ Quickstart

Java Client

The Java client is a blocking, java.net.Socket-based driver with no runtime dependencies, paired with a thread-safe VeltrixDBPool for use from multi-threaded servers.

Install

Maven:

xml
<dependency> <groupId>com.veltrixdb</groupId> <artifactId>veltrixdb-client</artifactId> <version>1.0.0</version> </dependency>

Gradle:

groovy
implementation 'com.veltrixdb:veltrixdb-client:1.0.0'

Requires Java 11+ at runtime (the client source is compiled targeting Java 17 in its own build). No runtime dependencies — VeltrixDBClient is built on plain java.net.Socket/javax.net.ssl.

Quick start

This example follows the class's own documented usage in VeltrixDBClient.java: open a connection, ping, then put/get/delete. VeltrixDBClient implements Closeable, so try-with-resources closes the socket automatically.

java
import com.veltrixdb.client.VeltrixDBClient; // Single connection (not thread-safe — use VeltrixDBPool for concurrent access) try (VeltrixDBClient c = new VeltrixDBClient("127.0.0.1", 9000)) { c.ping(); c.put("hello", "world".getBytes()); byte[] val = c.get("hello"); // null if not found System.out.println(new String(val)); // "world" c.delete("hello"); }

Config

VeltrixDBClient.Config lets you set timeouts and TLS explicitly instead of using the two-argument constructor:

java
VeltrixDBClient.Config cfg = new VeltrixDBClient.Config(); cfg.host = "prod-veltrix.internal"; cfg.port = 9000; cfg.connectTimeoutMs = 3_000; // TCP connect timeout (default 5000) cfg.socketTimeoutMs = 5_000; // per-operation read timeout (default 10000, 0 = none) cfg.sslContext = null; // non-null = TLS VeltrixDBClient c = new VeltrixDBClient(cfg);

API surface

Every data method throws IOException (network failure) and VeltrixDBException (server-side error response). These are checked exceptions in the actual source, so calling code must declare or catch them.

Core key-value

MethodDescription
ping()Check connection health
put(key, value)Write a key
get(key)Read a key. Returns null if not found
delete(key)Delete a key (no-op if already absent)
info()Get server stats string
auth(user, pass)Authenticate
close()Close the underlying socket (safe to call more than once)
isClosed()Whether the socket has been closed

Batch operations

MethodDescription
multiPut(entries)Write multiple keys. Returns Exception[] (null = success)
multiGet(keys)Read multiple keys. Returns MultiGetResult[]

Entry and MultiGetResult are static nested classes on VeltrixDBClient:

java
import com.veltrixdb.client.VeltrixDBClient.Entry; import java.util.List; List<Entry> entries = List.of( new Entry("user:1", "{\"name\":\"Alice\"}".getBytes()), new Entry("user:2", "{\"name\":\"Bob\"}".getBytes(), 60) // TTL 60s ); Exception[] errors = c.multiPut(entries); // errors[i] is null if that entry succeeded VeltrixDBClient.MultiGetResult[] results = c.multiGet(List.of("user:1", "user:missing")); // results[i].found is false, results[i].value is null when not found

Namespaces

MethodDescription
putNS(ns, key, value, ttl)Write into a namespace
getNS(ns, key)Read from a namespace
deleteNS(ns, key)Delete from a namespace
scanNamespace(ns, prefix, limit)Scan keys in a namespace, returns NSEntry[]
listNamespaces()List namespaces, returns NSInfo[]
dropNamespace(ns)Delete all keys in a namespace; returns the deleted count

Hash fields (per-field TTL)

MethodDescription
hset(key, field, value, ttl)Set a field with its own TTL
hget(key, field)Get a field value (null if not found/expired)
hdel(key, field)Delete one field
hgetAll(key)Get all live fields as HashField[]
hkeys(key)Get all live field names as String[]
hlen(key)Count live fields
hexpire(key, field, ttl)Update TTL of an existing field
httl(key, field)Remaining TTL (-1=forever, -2=not found)

Atomic operations

New in v1.1.0 — typed atomic ops (previously Rust/C++ only). Each method has an overload with a trailing ttlSeconds for the stored value (≤ 0 = no expiry); like the rest of the API, all of them throw IOException and VeltrixDBException:

MethodDescription
cas(key, expected, newValue) / cas(key, expected, newValue, ttlSeconds)Compare-and-swap; returns a CasResult enum: SWAPPED, MISMATCH, or NOT_FOUND
incr(key) / incr(key, delta) / incr(key, delta, ttlSeconds)Atomically add delta (default 1); returns the new value as long. Missing keys start from 0
decr(key) / decr(key, delta) / decr(key, delta, ttlSeconds)Atomically subtract delta (default 1); returns the new value as long. Missing keys start from 0
setnx(key, value) / setnx(key, value, ttlSeconds)Set only if absent; returns true when the key was created, false when it already existed

CasResult is a nested enum on VeltrixDBClient:

java
import com.veltrixdb.client.VeltrixDBClient.CasResult; // Counter — missing key starts from 0 long n = c.incr("counter", 5); // 5 n = c.decr("counter", 2); // 3 // Compare-and-swap CasResult r = c.cas("hello", "world".getBytes(), "earth".getBytes()); switch (r) { case SWAPPED: System.out.println("replaced"); break; case MISMATCH: System.out.println("value did not match"); break; case NOT_FOUND: System.out.println("key does not exist"); break; } // Set-if-absent with a 30-second TTL (lock-style) boolean acquired = c.setnx("lock", "owner-A".getBytes(), 30);

Connection pool (thread-safe)

VeltrixDBPool wraps an ArrayBlockingQueue<VeltrixDBClient> and pre-dials poolSize connections in its constructor. This is the class's own documented quick start:

java
import com.veltrixdb.client.VeltrixDBPool; VeltrixDBPool.Config cfg = new VeltrixDBPool.Config(); cfg.host = "127.0.0.1"; cfg.port = 9000; cfg.poolSize = 16; try (VeltrixDBPool pool = new VeltrixDBPool(cfg)) { // Functional style — acquire/release handled automatically pool.execute(c -> { c.put("key", "value".getBytes()); return null; }); byte[] val = pool.execute(c -> c.get("key")); }

Manual acquire/release is also supported when you need to hold a connection across multiple calls:

java
VeltrixDBClient c = pool.acquire(); try { c.put("x", data); pool.release(c); } catch (Exception e) { c.close(); // broken conn — don't return to pool pool.replenish(); // replace it throw e; }

VeltrixDBPool.Config extends VeltrixDBClient.Config, adding poolSize (default 8), acquireTimeoutMs (default 5000), and optional username/password for auto-auth on every new connection. pool.available() reports the current idle-connection count.

TLS

java
import javax.net.ssl.*; import java.security.KeyStore; // Server-only verification SSLContext ctx = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("truststore.jks"), "password".toCharArray()); tmf.init(ks); ctx.init(null, tmf.getTrustManagers(), null); VeltrixDBClient.Config cfg = new VeltrixDBClient.Config(); cfg.host = "veltrix.example.com"; cfg.port = 9443; cfg.sslContext = ctx; VeltrixDBClient c = new VeltrixDBClient(cfg);

Auth

java
// Single connection VeltrixDBClient c = new VeltrixDBClient("127.0.0.1", 9000); c.auth("alice", "secret"); c.put("key", "value".getBytes()); // Pool with auto-auth VeltrixDBPool.Config cfg = new VeltrixDBPool.Config(); cfg.username = "alice"; cfg.password = "secret"; VeltrixDBPool pool = new VeltrixDBPool(cfg); // all connections auto-auth on connect

Error handling

java
try { byte[] val = c.get("key"); if (val == null) { // key not found — not an exception } } catch (VeltrixDBException e) { // server returned an error status } catch (java.net.SocketTimeoutException e) { // operation timed out } catch (java.io.EOFException e) { // connection dropped by the server }

VeltrixDBException (extends Exception) is thrown for any non-OK, non-NOT_FOUND status the server returns; it optionally wraps a lower-level Throwable cause. Missing keys and missing hash fields return null rather than throwing — check for null first.