Skip to main content

Consume live data

Push-based monitoring: a subscription names a set of time-series, and a live connection delivers each new datapoint as it lands — no polling. A control-room dashboard, an alerting worker, or a downstream pipeline drives the loop and acks what it has handled. Anything unacked is redelivered, so a crash never loses data.

1. Create a subscription

Subscription sub = new Subscription();
sub.setExternalId("engine_room");
sub.setName("Engine room");
sub.setTimeseries(List.of(
IdCollection.createFromExternalId("engine_temperature"),
IdCollection.createFromExternalId("engine_rpm")));
client.subscriptions().create(List.of(sub));

2. Listen and ack

Hand each message to a handler (or drive a loop yourself), and ack once you've durably handled it. Make the handler idempotent — a redelivery after a crash will replay the last unacked messages.

Register a handler with stream — a dedicated virtual thread delivers each message as it arrives and acks it once your handler returns (or nacks it if the handler throws). The returned handle stops delivery and closes the listener, so use try-with-resources.

import ai.intellistream.datahub.sdk.subscriptions.SubscriptionMessage;

try (var stream = client.subscriptions().listen(List.of("engine_room"))
.stream((SubscriptionMessage msg) -> handle(msg.payload()))) { // auto-acks on return
awaitShutdown(); // your app's lifecycle; closing the handle ends the stream
}

Prefer a loop, or want to ack on your own schedule? Drive poll yourself — it blocks up to the timeout and returns null on a quiet interval (it is a blocking queue hand-off, not network polling):

import ai.intellistream.datahub.sdk.subscriptions.SubscriptionListener;
import java.time.Duration;

try (SubscriptionListener listener = client.subscriptions().listen(List.of("engine_room"))) {
while (running) {
SubscriptionMessage msg = listener.poll(Duration.ofSeconds(5));
if (msg == null) continue;
handle(msg.payload()); // event action + affected datapoints
listener.ack(msg.messageId());
}
}

Change the interest set at runtime

A long-lived listener doesn't need to reconnect to follow more (or fewer) series — subscribe / unsubscribe adjust it in place.

listener.subscribe(List.of("engine_oil_pressure"));
listener.unsubscribe(List.of("engine_rpm"));
nack to retry later

If a message can't be processed right now (a downstream system is down), nack it instead of acking — it will be redelivered rather than dropped. With stream, throwing from the handler nacks for you; to control acks explicitly use stream(handler, AckMode.MANUAL) and call ack/nack yourself. With poll, just call nack instead of ack.