Skip to content

Data Structures

LoomCache is more than a KV store. The server implements a broad catalogue of distributed structures; the client SDK currently exposes the most commonly used subset over the wire protocol. Anything below marked server-side only exists in loom-server/src/main/java/com/loomcache/server/datastructures with tests, but does not yet have a dedicated client wrapper.

For the production-supported single-group path, every committed write flows through Raft: replicated to a majority of nodes, persisted to WAL, and applied atomically to the state machine before the client response is sent. Multi-group sharding remains unsupported/fail-closed in production until per-group WAL/snapshot recovery exists.

Distributed Data Structures

7 built-in primitives. Fast, durable, and strictly linearizable.

"user:101"{ name: "Alice" }
"config:rateLimit"5000
"session:temp"Writing...
TTL: 30s
LoomMap<String, String> users = client.getMap("users");
users.put("alice", "Alice");
String name = users.get("alice"); // near cache may answer locally
users.putIfAbsent("bob", "Bob"); // atomic
users.delete("alice");

Supported operations: get, put, putIfAbsent, putAll, delete, containsKey, size, getAll, getAndRemove, computeIfAbsent, cursor-based scan / scanner, and async variants (getAsync, putAsync, …). Stats are available via LoomMap.getStats().

Reads are linearizable by default: leaders use lease/read-index checks and followers redirect to the leader. Embedded or member-local deployments can opt into readBackupData(true) / loomcache.server.read-backup-data=true to serve reads from the local replica; this trades latency for possible staleness during replication lag or leader failover.

Embedded/server maps expose MapStore and EntryStore integration points for non-production integration testing. Production profiles fully disable/fail-close MapStore, MapLoader, EntryStore, and generic JDBC MapStore declarations in this release. They are not a replacement for the Raft WAL/snapshot durability contract.

Server-side LRU, LFU, finite max-entry/max-memory eviction, and max-idle semantics are also not production-supported until eviction decisions are Raft-applied and proven through WAL/snapshot/restart tests.

LoomQueue<String> tasks = client.getQueue("tasks");
tasks.offer("send-email");
String next = tasks.poll();
String peek = tasks.peek();

offer, poll, peek, size, offerAll, bounded poll(int), drain, drainTo, plus async variants. Embedded QueueStore exists as an SPI, but snapshot/restart parity is not production-supported until queue restore, rollback, and duplicate/lost item failure windows are certified.

LoomSet<String> tags = client.getSet("tags");
tags.add("java");
tags.contains("cache");
tags.size();

add, remove, contains, size, clear, cursor scan, async variants.

LoomTopic<String> events = client.getTopic("events", String.class);
int sub = events.subscribe(msg -> System.out.println("got: " + msg));
events.publish("hello");
events.unsubscribe(sub);

Typed publish/subscribe over the current client-managed polling path. Subscription ids are unique per client connection; closeSubscriptions() drops them all. Do not assume Hazelcast-style push dispatch semantics.

LoomAtomicLong counter = client.consistencySubsystem().getAtomicLong("hits");
counter.incrementAndGet();
long cur = counter.get();
counter.compareAndSet(cur, cur + 10);

Fully Raft-replicated through CP_ATOMIC_* opcodes: get, set, incrementAndGet, decrementAndGet, addAndGet, getAndIncrement, getAndDecrement, getAndAdd, compareAndSet.

LoomLinearizableLock / semaphore wire APIs

Section titled “LoomLinearizableLock / semaphore wire APIs”

Present in the client SDK, but production servers reject CP_LOCK_* and CP_SEMAPHORE_* opcodes with an unsupported-operation response. These APIs stay fail-closed until session lifecycle opcodes for create/heartbeat/close/expiry/force-close are part of the Raft-backed wire contract. Use the in-process ConsistencySubsystem only for non-production embedded scenarios.

client.batch()
.mapPut("users", "alice", "Alice")
.mapDelete("users", "eve")
.execute();

Single BATCH_EXECUTE request — all operations commit atomically or roll back together under the server’s mutation lock.

Server-side only (no dedicated client wrapper yet)

Section titled “Server-side only (no dedicated client wrapper yet)”
  • DistributedMultiMap, DistributedList, DistributedPriorityQueue, DistributedRingbuffer (readManyAsync supports server-side IFunction filtering, and RingbufferStore supports embedded persistence).
  • ReliableTopic — ringbuffer-backed pub/sub with monotonic sequence numbers and replay.
  • ContinuousQueryCache — server-side filtered map view that auto-updates via change events.
  • SnowflakeIdGenerator.
  • CRDTs: PNCounter, GSet, ORSet, LWWRegister (managed by CrdtManager).
  • CP primitives: LinearizableLock, LinearizableSemaphore, LinearizableLatch, LinearizableAtomicReference — usable only in embedded/non-production deployments unless the release notes explicitly mark the corresponding wire path production-supported.

See Roadmap for the plan to expose these over the wire.