Skip to main content

Module capability

Module capability 

Source
Expand description

Cluster-wide capability negotiation.

Every node advertises a set of typed capabilities at the gossip handshake. For each capability name the cluster picks the lowest-common-denominator value: the highest local value that the peer also supports, falling back to a “floor” value when there is no overlap. The mechanism mirrors the design of riak_core_capability and is intended to let us land wire-format changes (e.g. dnode framing v2, AAE tree format v2) behind feature flags that flip on automatically once every peer in a mixed-version cluster reports support.

The public surface is small:

  • Capability - the trait each capability implements; it carries the typed value, the local supported set, and the merge rule.
  • CapabilityRegistry - the per-node registry that owns capability instances, generates the local advertisement, and resolves negotiated values.
  • CapabilityAd - the wire-bound advertisement (a list of (name, supported_values)).
  • NegotiatedCapabilities - the result of a single negotiation, keyed by capability name.

§Wire encoding

CapabilityAd travels on the wire inside the dnode handshake (see crate::proto::dnode::Handshake). The encoding is a simple length-prefixed binary layout that uses only the standard library; no external codec is dragged in.

§Examples

use dynomite::cluster::capability::{Capability, CapabilityRegistry};

struct Framing;
impl Capability for Framing {
    type Value = u32;
    fn name(&self) -> &'static str { "framing" }
    fn supported_values(&self) -> Vec<u32> { vec![1, 2] }
    fn merge(&self, peer: &[u32]) -> Option<u32> {
        self.supported_values()
            .into_iter()
            .filter(|v| peer.contains(v))
            .max()
    }
    fn encode_value(&self, v: &u32) -> Vec<u8> { v.to_le_bytes().to_vec() }
    fn decode_value(&self, b: &[u8]) -> Option<u32> {
        <[u8; 4]>::try_from(b).ok().map(u32::from_le_bytes)
    }
}

let mut reg = CapabilityRegistry::new();
reg.register(Framing);
let ad = reg.local_advertise();
assert_eq!(ad.entries().len(), 1);

Structs§

AaeTreeFormat
Stock capability advertising the supported AAE tree formats.
CapabilityAd
On-the-wire advertisement built by CapabilityRegistry::local_advertise.
CapabilityAdEntry
One entry in a CapabilityAd: a capability name and the list of opaque, capability-defined value blobs the advertising peer supports.
CapabilityRegistry
Per-node registry that owns capability instances, generates the local advertisement, and stores the most recently negotiated value for each capability.
CrdtObjectFormat
Stock capability advertising the supported CRDT object wire formats.
DnodeFramingVersion
Stock capability advertising the supported dnode framing versions on this build. Today the local set is [1, 2]; v1 is the implemented framing and v2 is reserved for the next stage’s wire upgrade.
GossipPhiNegotiable
Stock capability advertising whether this node will accept a dynamic phi threshold pushed by the cluster.
NegotiatedCapabilities
Outcome of a single round of negotiation.

Enums§

CapabilityCodecError
Errors produced while decoding a CapabilityAd blob.

Constants§

CAP_AAE_TREE_FORMAT
Capability name for the active append-anti-entropy tree format. Reserved for future format upgrades; today only v1 is implemented.
CAP_CRDT_OBJECT_FORMAT
Capability name for the on-the-wire CRDT object format used by the entropy reconciliation path.
CAP_DNODE_FRAMING_VERSION
Capability name shipped in the v0.0.1 registry.
CAP_GOSSIP_PHI_NEGOTIABLE
Capability name for whether the peer accepts a dynamic phi threshold negotiated at runtime.

Traits§

Capability
Trait every capability implements.

Functions§

default_registry
Construct a registry pre-populated with the v0.0.1 stock capabilities: dnode framing version, AAE tree format, CRDT object format, and the dynamic-phi-threshold flag.