hive-c0re: converge when the controller republishes, not only at boot
The wanted-state read was a boot-time DAG node, so a swarm-level change sat unapplied until the next restart. This watches the hive's own bucket and converges on each update. It does not replace the boot read: a watch hears only what is published while it is listening, so a hive that was down still learns the current declaration from `pull`. The watch is the fast path, `pull` stays the repair path. Rides the connection swarm-status already opens, as a third consumer — a second connect would double the auth-callout traffic and give the two paths independent reconnect state, which is the reason the deploy-event drain is spawned there too. A delete is not a deletion order. `carries_a_declaration` is pure and tested so that rule is enforced rather than asserted: converging on a withdrawn key would tear down exactly the agents "absence is not a deletion order" protects.
This commit is contained in:
parent
d6d60ff06e
commit
5f733493f1
3 changed files with 146 additions and 1 deletions
|
|
@ -154,6 +154,27 @@ pub async fn open_read_only(
|
|||
js.get_key_value(bucket(hive)).await.ok()
|
||||
}
|
||||
|
||||
/// Watch this hive's own declaration for changes.
|
||||
///
|
||||
/// **Hive-side.** `None` on the same terms as [`open_read_only`] — no bucket
|
||||
/// yet — plus one more: a watch is a `JetStream` *consumer*, so it needs a grant
|
||||
/// a plain `get` does not. A hive missing `CONSUMER.CREATE` on its own stream
|
||||
/// gets `None` here while `get` keeps working, which is why the caller must
|
||||
/// treat this as "not watching yet" and retry rather than as a dead end.
|
||||
///
|
||||
/// Updates only, deliberately: the boot-time read already has the current
|
||||
/// value, and a watch that replayed history would re-converge the whole
|
||||
/// declaration on every reconnect for nothing.
|
||||
#[cfg(feature = "kv")]
|
||||
pub async fn watch(
|
||||
client: &async_nats::Client,
|
||||
hive: &str,
|
||||
) -> Option<async_nats::jetstream::kv::Watch> {
|
||||
// The bucket holds exactly one key, named for the hive — same key
|
||||
// `open_read_only`'s caller reads, so both paths address one declaration.
|
||||
open_read_only(client, hive).await?.watch(hive).await.ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AgentState, BUCKET_PREFIX, HiveWanted, bucket};
|
||||
|
|
|
|||
Loading…
Reference in a new issue