Cached Query
Cache KubeMQ Query responses with the Java SDK using a cache key and TTL to serve repeated requests faster.
Overview
Query response caching lets the broker answer repeat requests without re-running your handler — useful when a query is expensive to compute (a database lookup, an aggregation, a downstream call) but the same input is asked for repeatedly in a short window. Only the first request pays the processing cost; every other caller gets the same answer straight from the broker.
Set cacheKey(...) and cacheTtlInSeconds(...) on the QueryMessage. The first query with a given key is a miss: it reaches the handler, and the broker stores the response under that key for the TTL. A subsequent query with the same key is a hit — the broker returns the stored response directly, and the handler is not invoked again until the TTL expires.
Gotchas: the cache is keyed by the string you choose, not by the query body — if the underlying data changes mid-TTL, callers can get a stale answer until it expires. Keys are scoped per channel, so the same key on another channel is a separate entry. Setting cacheTtlInSeconds(0) or omitting cacheKey disables caching for that request even on a caching channel.
Prerequisites
- KubeMQ server running on
localhost:50000 - Java SDK installed (
implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1'(Gradle) or Maven dependency from Getting Started)
Code
package io.kubemq.example.queries;
import io.kubemq.sdk.cq.*;
public class CachedQueryExample {
private static final String ADDRESS = "localhost:50000";
private static final String CLIENT_ID = "java-queries-cached-query-client";
private static final String CHANNEL = "java-queries.cached-query";
public static void main(String[] args) throws InterruptedException {
// Create a client connected to the KubeMQ server
CQClient client = CQClient.builder().address(ADDRESS).clientId(CLIENT_ID).build();
client.ping();
// Create the queries channel
client.createQueriesChannel(CHANNEL);
// Subscribe to handle queries (responses may be cached)
QueriesSubscription sub = QueriesSubscription.builder()
.channel(CHANNEL)
.onReceiveQueryCallback(query -> {
System.out.println("Handler invoked for: " + query.getId());
client.sendResponseMessage(QueryResponseMessage.builder()
.queryReceived(query).isExecuted(true)
.body("cached-result".getBytes()).build());
})
.onErrorCallback(err -> System.err.println("Error: " + err.getMessage()))
.build();
// Start the query handler subscription
client.subscribeToQueries(sub);
Thread.sleep(1000);
// Build query with cache key and TTL
QueryMessage q = QueryMessage.builder()
.channel(CHANNEL).body("get-price".getBytes()).metadata("product=xyz")
.timeoutInSeconds(10).cacheKey("price:xyz").cacheTtlInSeconds(60).build();
// First request hits the handler; second may be served from cache
QueryResponseMessage r1 = client.sendQuery(q);
System.out.println("Response 1: " + new String(r1.getBody()));
QueryResponseMessage r2 = client.sendQuery(q);
System.out.println("Response 2: " + new String(r2.getBody()) + " (may be cached)");
// Clean up resources
sub.cancel();
client.deleteQueriesChannel(CHANNEL);
client.close();
}
}
How It Works
cacheKey("price:xyz")andcacheTtlInSeconds(60)instruct the broker to store the first response for this key and serve it directly for subsequent identical requests within 60 seconds, bypassing the handler entirely.- The first
sendQuery()reaches the handler (you see "Handler invoked"); the second call returns the cached response — the handler is not invoked again until the TTL expires. - Cache keys are scoped to the channel; the same key on different channels is independent.
- Set
cacheTtlInSeconds(0)or omitcacheKeyto disable caching for a specific request even on a channel that supports it.
Related
Was this page helpful?