No behaviour change. Casts replaced by try_from / Duration math; schedules.rs reuses agent_renewal::unix_now; the five swarm-queue-client KV open-or-create copies share one private kv::open_or_create.
61 lines
2.8 KiB
Rust
61 lines
2.8 KiB
Rust
//! The hive-status KV bucket: its name, and the shape it is created with.
|
|
//!
|
|
//! Two processes touch this bucket from opposite ends — a hive writes its
|
|
//! own key, the swarm controller reads every key — and they live in
|
|
//! different crates. That is the whole reason this module exists rather
|
|
//! than a `const` on each side: **the two ends must agree, and a literal
|
|
//! repeated across crates is an agreement nothing checks.**
|
|
//!
|
|
//! The name is the obvious half. The sharper half is the *config*: both
|
|
//! ends open the bucket with `open_or_create`, because either may
|
|
//! arrive first on a fresh swarm and neither can assume the other has
|
|
//! run. If the two ends passed different `Config`s, whichever created it
|
|
//! would win and the other's `get_key_value` would succeed against a
|
|
//! bucket it did not ask for — no error, no log, just a retention policy
|
|
//! nobody chose. Sharing the constructor makes the race have one outcome
|
|
//! instead of two.
|
|
//!
|
|
//! The bucket *name* is unconditional; only `open_or_create` is behind the
|
|
//! `kv` feature. (Named in backticks rather than linked: with `kv` off the item
|
|
//! does not exist, and an intra-doc link to it fails the rustdoc gate in
|
|
//! exactly the configuration this split exists to support.) A third end names the bucket without ever opening it — the
|
|
//! auth-callout responder, which derives the subjects a hive may publish to
|
|
//! from it — and it speaks neither `jetstream` nor `kv`. Gating the name too
|
|
//! would have made that consumer choose between a JetStream stack it does not
|
|
//! use and a copied literal, and a copied literal is precisely the agreement
|
|
//! nothing checks.
|
|
|
|
#[cfg(feature = "kv")]
|
|
use crate::Error;
|
|
|
|
/// The KV bucket hives publish their status snapshots into, one key per
|
|
/// hive keyed by `hiveName`.
|
|
///
|
|
/// A constant and not an option: reader and writer must name the same
|
|
/// bucket, and an option is a way for two deployments to disagree about
|
|
/// which one that is. Nothing about a bucket name is site-specific.
|
|
pub const BUCKET: &str = "hive-status";
|
|
|
|
/// Open the status bucket, creating it if nothing has yet.
|
|
///
|
|
/// `history: 1` is the shape: every consumer reads *the last thing each
|
|
/// hive said*, and retaining more would be storage bought for a query
|
|
/// nobody makes.
|
|
///
|
|
/// Creating rather than requiring a provisioning step is deliberate — the
|
|
/// controller and the hives come up in no particular order, and a bucket
|
|
/// that must pre-exist turns "the swarm was deployed in the wrong order"
|
|
/// into a permanent, silent absence of data.
|
|
#[cfg(feature = "kv")]
|
|
pub async fn open_or_create(
|
|
client: &async_nats::Client,
|
|
) -> Result<async_nats::jetstream::kv::Store, Error> {
|
|
let js = async_nats::jetstream::new(client.clone());
|
|
crate::kv::open_or_create(
|
|
&js,
|
|
BUCKET,
|
|
"status",
|
|
"Last status snapshot offered by each hive".to_owned(),
|
|
)
|
|
.await
|
|
}
|