Skip to content

Client API Reference

Client SDK Architecture

Smart routing, near cache, pipelining, and auto-retry built in.

LoomClientApp Thread
LIFO Pool (5-20)
node-1
node-2
node-3

The client SDK lives in loom-client and targets Java 17+. The root class is LoomClient; async variants come from AsyncLoomClient.

The published Java API documentation is generated from the Maven aggregate Javadoc target and deployed with this docs site at /api/javadoc/. Build it locally with:

Terminal window
mvn -q -DskipTests -DskipITs -DskipIntegrationTests javadoc:aggregate
LoomClient client = LoomClient.builder()
.addSeed("127.0.0.1:5701")
.addSeed("127.0.0.1:5702")
.addSeed("127.0.0.1:5703")
.connectionTimeout(Duration.ofSeconds(5))
.requestTimeout(Duration.ofSeconds(15))
.maxRetries(3)
.retryBaseDelay(Duration.ofMillis(100))
.tlsConfig(TlsConfig.disabled())
.auth("alice", "admin,operator") // optional — forwarded on AUTH handshake
.nearCacheEnabled(true)
.nearCacheTtl(Duration.ofSeconds(30))
.nearCacheMaxSize(10_000)
.build();
client.connect();

Every builder method exists on LoomClient.Builder — any property not listed above is not currently supported.

LoomMap<K,V> generics are a Java client convenience, not Hazelcast-style implicit object mode. In this release, arbitrary POJO map values are not production-supported; use the documented scalar and binary value encodings until the public map path is certified through client round-trip, Raft apply, WAL replay, snapshot restore, and restart tests.

CategoryMethods
Readget(K), containsKey(K), size(), getAll(Collection<K>)
Writeput(K, V), putIfAbsent(K, V), putAll(Map), delete(K), getAndRemove(K)
AtomiccomputeIfAbsent(K, Function<K, V>)
Iteratescan(cursor), scan(cursor, pattern), scan(cursor, pattern, count); scanner(), scanner(pattern), scanner(pattern, pageSize)
Per-callget(K, Duration), put(K, V, Duration), delete(K, Duration), containsKey(K, Duration)
AsyncgetAsync, putAsync, deleteAsync, containsKeyAsync, sizeAsync
StatsgetStats()LoomMapStats(hits, misses, requests, errors, hitRatePercent)
  • offer(E), poll(), peek(), plus offerAsync, pollAsync, peekAsync.
  • add, remove, contains, size, clear, scan / scanner, and async variants.

LoomTopic<T>client.getTopic(name) / client.getTopic(name, Class<T>)

Section titled “LoomTopic<T> — client.getTopic(name) / client.getTopic(name, Class<T>)”
  • publish(T), subscribe(Consumer<T>) → subscription id, unsubscribe(id), closeSubscriptions(), activeSubscriptionCount().
  • Failure counters: getDecodeFailureCount(), getListenerFailureCount().

CP primitives — client.consistencySubsystem()

Section titled “CP primitives — client.consistencySubsystem()”
LoomConsistencySubsystem cp = client.consistencySubsystem();
LoomAtomicLong counter = cp.getAtomicLong("hits");
counter.incrementAndGet();
counter.compareAndSet(10, 20);
LoomLinearizableLock lock = cp.getLock("resource"); // wire path fails closed in production
  • LoomAtomicLong — fully Raft-replicated via CP_ATOMIC_*.
  • LoomLinearizableLock — API ships client-side, but the server currently rejects CP_LOCK_* with an unsupported-operation response. CP_SEMAPHORE_* is in the same unsupported/fail-closed production class until session create/heartbeat/close/expiry/force-close opcodes exist and recover through Raft. Use the embedded ConsistencySubsystem only for non-production embedded scenarios.
client.batch()
.mapPut("users", "alice", "Alice")
.mapPut("users", "bob", "Bob")
.mapDelete("users", "eve")
.execute();

A single BATCH_EXECUTE request runs atomically under the server’s mutation lock.

Run SQL against a named map and receive a LoomSqlResult:

// User must have an explicit supported serializer/encoding before production use.
LoomMap<String, User> users = client.getMap("users");
LoomSqlResult result = users.query("SELECT key, name, age FROM users WHERE age > 30");

See SQL engine for supported syntax. CREATE INDEX and declarative SQL indexes are unsupported/rejected in this release; full-scan fallback is not Hazelcast index parity.

AsyncLoomClient returns CompletableFutures for the same operations. Use it when you need non-blocking composition.

Under com.loomcache.client.cache:

  • NearCache — sized LRU with TTL, updated by server-push invalidations.
  • ReadThroughCache, AsyncReadThroughCache — cache-loader fronted with single-flight coalescing.
  • WriteBehindCache — in-process buffer with asynchronous flush to the cluster.
  • CacheLoader, AsyncCacheLoader — SPIs you implement.
  • RetryPolicy — exponential backoff with jitter, retries only retryable exceptions.
  • RequestRouter — partition-aware, collision retry, leader fallback.
  • LeaderTracker — caches the last known leader; cleared explicitly or on authenticated redirect.
  • ClientRequestDeduplicator — stamps mutating requests with <clientId, sequence> for server-side dedupe of retries.
  • 16-byte header: magic | opcode | correlationId | bodyLen | flags | keyLen | status | reserved.
  • 108 opcodes in MessageType.java.
  • Response opcodes: RESPONSE_OK, RESPONSE_ERROR, RESPONSE_NOT_FOUND, RESPONSE_REDIRECT, RESPONSE_SERVER_BUSY, RESPONSE_SEQUENCE_LOST.