Watch
0
0
Fork
You've already forked hyperhive
0

archetype flows on the board list the agents the router sends to, and the docs say a switch-off key outlives its flow

This commit is contained in:
atlas 2026-11-11 20:45:07 +01:00 • committed by mara
commit 13ff33ead0
2 changed files with 66 additions and 30 deletions

View file

@ -16,7 +16,7 @@ edition.workspace = true
# client; the exception exists because an agreement between two crates has
# to live in one of them, and neither end of that bucket is senior to the
# other.
kv = ["async-nats/kv"]
kv = ["async-nats/kv", "dep:futures-util"]
# 🩸 `jetstream` is NOT in async-nats's default feature set here — the
# workspace-level dependency turns default features off entirely (see
# root `Cargo.toml`: `server_2_14`/`nkeys`/`ring` only). `kv` above works
@ -83,6 +83,8 @@ router-todo = ["async-nats/jetstream"]
# above - the connect itself needs none of them.
async-nats.workspace = true
hive-types = { workspace = true, optional = true }
# `agent_status::roster` collects the stream's subject listing.
futures-util = { workspace = true, optional = true }
# `blocking` on top of the workspace default (`form`/`json`/`rustls`) —
# `mint_token_for_blocking` needs `reqwest::blocking::Client` for a caller
# with no tokio reactor to `.await` an async request on (an OTLP exporter's

View file

@ -20,3 +20,34 @@ pub async fn open_or_create(
)
.await
}
/// The agents of the swarm: the agent names in the bucket's keys
/// (`<hive>.<agent>`), read from the stream's subject list. This is the
/// roster the notification router sends to.
///
/// # Errors
///
/// The bucket's stream cannot be opened or its subjects listed.
#[cfg(feature = "kv")]
pub async fn roster(
client: &async_nats::Client,
) -> Result<std::collections::BTreeSet<String>, Box<dyn std::error::Error + Send + Sync>> {
use futures_util::TryStreamExt as _;
let bucket = swarm_wire::agent_status::BUCKET;
let js = async_nats::jetstream::new(client.clone());
let stream = js.get_stream(format!("KV_{bucket}")).await?;
let subjects: Vec<(String, usize)> = stream
.info_with_subjects(format!("$KV.{bucket}.>"))
.await?
.try_collect()
.await?;
let prefix = format!("$KV.{bucket}.");
Ok(subjects
.into_iter()
.filter_map(|(subject, _)| {
let key = subject.strip_prefix(&prefix)?;
swarm_wire::agent_status::split_key(key).map(|(_, agent)| agent.to_owned())
})
.collect())
}