List Subjects for a Specific Stream in JetStream
All clients have a way to get the list of subjects for any given stream, except it’s not completely obvious how to do this. These examples will show you how to get the list of subjects.
$ nbe run jetstream/list-subjects/denoView the source code or learn how to run this example yourself
Code
import {
connect,
nuid
} from "https://deno.land/x/nats@v1.28.0/src/mod.ts";
const servers = Deno.env.get("NATS_URL")?.split(",");
const nc = await connect({ servers });
const jsm = await nc.jetstreamManager();
const js = nc.jetstream();
Create a stream with a few random subjects
const plainSubj = `PLAIN_${nuid.next().substring(18)}`;
const gtSubj = `GT_${nuid.next().substring(18)}`;
const starSubj = `STAR_${nuid.next().substring(18)}`;
const name = `EVENTS_${nuid.next().substring(18)}`;
let si = await jsm.streams.add({
name,
subjects: [plainSubj, `${gtSubj}.>`, `${starSubj}.*`]
});
console.log(`Stream: ${si.config.name} has these subjects: '${si.config.subjects}'`)
Get stream info with StreamInfoRequestOptions
Get the subjects via the streams.info call. Since this is “state” there are no subjects in the state unless there are messages in the subject.
si = await jsm.streams.info(name, {subjects_filter: ">"});
const count = si.state.subjects
? Object.getOwnPropertyNames(si.state.subjects).length
: 0;
console.log(`Before publishing any messages, there should be 0 subjects in the state: ${count}`)
console.log(Before publishing any messages, there are 0 subjects: ${si.state.num_subjects}
)
Publish a message
await js.publish(plainSubj)
si = await jsm.streams.info(name, {subjects_filter: ">"});
console.log("After publishing a message to a subject, it appears in state:")
if (si.state.subjects) {
for (const [key, value] of Object.entries(si.state.subjects)) {
console.log(` subject '${key}' has ${value} message(s)`)
}
}
Publish some more messages, this time against wildcard subjects
await js.publish(`${gtSubj}.A`, "gtA-1");
await js.publish(`${gtSubj}.A`, "gtA-2");
await js.publish(`${gtSubj}.A.B`, "gtAB-1");
await js.publish(`${gtSubj}.A.B`, "gtAB-2");
await js.publish(`${gtSubj}.A.B.C`, "gtABC");
await js.publish(`${gtSubj}.B.B.B`, "gtBBB");
await js.publish(`${starSubj}.1`, "star1-1");
await js.publish(`${starSubj}.1`, "star1-2");
await js.publish(`${starSubj}.2`, "star2");
Get all subjects
si = await jsm.streams.info(name, {subjects_filter: ">"});
console.log("Wildcard subjects show the actual subject, not the template.");
if (si.state.subjects) {
for (const [key, value] of Object.entries(si.state.subjects)) {
console.log(` subject '${key}' has ${value} message(s)`)
}
}
Subject Filtering
Instead of allSubjects, you can filter for a specific subject
si = await jsm.streams.info(name, {subjects_filter: `${gtSubj}.>`});
console.log(`Filtering the subject returns only matching entries ['${gtSubj}.>']`);
if (si.state.subjects) {
for (const [key, value] of Object.entries(si.state.subjects)) {
console.log(` subject '${key}' has ${value} message(s)`)
}
}
si = await jsm.streams.info(name, {subjects_filter: `${gtSubj}.A.>`});
console.log(`Filtering the subject returns only matching entries ['${gtSubj}.A>']`);
if (si.state.subjects) {
for (const [key, value] of Object.entries(si.state.subjects)) {
console.log(` subject '${key}' has ${value} message(s)`)
}
}
await nc.close();
Output
Stream: EVENTS_7Q3G has these subjects: 'PLAIN_7PKV,GT_7PR2.>,STAR_7PX9.*' Before publishing any messages, there should be 0 subjects in the state: 0 After publishing a message to a subject, it appears in state: subject 'PLAIN_7PKV' has 1 message(s) Wildcard subjects show the actual subject, not the template. subject 'GT_7PR2.A' has 2 message(s) subject 'GT_7PR2.A.B' has 2 message(s) subject 'GT_7PR2.A.B.C' has 1 message(s) subject 'GT_7PR2.B.B.B' has 1 message(s) subject 'PLAIN_7PKV' has 1 message(s) subject 'STAR_7PX9.1' has 2 message(s) subject 'STAR_7PX9.2' has 1 message(s) Filtering the subject returns only matching entries ['GT_7PR2.>'] subject 'GT_7PR2.A' has 2 message(s) subject 'GT_7PR2.A.B' has 2 message(s) subject 'GT_7PR2.A.B.C' has 1 message(s) subject 'GT_7PR2.B.B.B' has 1 message(s) Filtering the subject returns only matching entries ['GT_7PR2.A>'] subject 'GT_7PR2.A.B' has 2 message(s) subject 'GT_7PR2.A.B.C' has 1 message(s)
Recording
Note, playback is half speed to make it a bit easier to follow.