跳至主要内容

Event Federation reference

Experimental (CloudEdge). See ADR 0006: CloudEdge Event Federation for the design and invariants, and the how-to Event Federation subscription for a worked example.

Event Federation lets routerd nodes exchange typed, observed facts (e.g. "this client IPv4 was observed", "this address expired") over the overlay, and lets a subscriber turn matched events into derived configuration via a plugin. It is the control-plane substrate beneath Selective Address Mobility: an observed address on one node becomes a RemoteAddressClaim (capture) on another.

The model is at-least-once delivery with idempotent, observed-fact events. Events are immutable statements about the world ("observed"), never imperative commands; a receiver re-deriving the same state from the same events is a no-op.

Kinds

EventGroup

The bus a node participates in. One node has one identity per group.

FieldMeaning
nodeNameThis node's identity in the group; stamped as sourceNode on emitted events.
retentionBounds how many events / how long the local store keeps them. Empty/zero = unlimited.
authHMAC secret material for peer delivery (push).
listenReceiver bind (address) for inbound peer pushes. Empty = push-only (no receiver).
replayWindowGo duration bounding accepted message timestamp skew for replay protection (default 5m).

EventPeer

A remote node this node pushes events to.

FieldMeaning
groupRefThe EventGroup this peer belongs to (required).
nodeNameRemote peer node identity (required).
endpointBase URL to push to, e.g. http://10.99.0.7:8787 (required for push).
directionDelivery direction; only push is supported. Empty defaults to push.
typesOptional event-type allowlist; empty delivers all.
subjectPrefixesOptional subject-prefix allowlist; empty delivers all.

EventSubscription

Turns matched events into a plugin invocation that emits a DynamicConfigPart.

FieldMeaning
groupRefThe EventGroup to consume from.
matchWhich events to act on (by type / subject).
trigger.pluginRefThe Plugin invoked for matched events.
trigger.batchWindowCoalesce matched events into one invocation (Go duration).
trigger.debounceDelay invocation until after the last matched event (Go duration).

routerctl federation CLI

routerctl federation event emit --group <g> --type <topic> --subject <entity> [--source-node <n>] [--ttl <dur>] [--payload k=v ...]
routerctl federation event list --group <g>
routerctl federation event deliveries --group <g>

emit records an observed fact into the local store (e.g. --type routerd.client.ipv4.observed --subject 10.88.60.9/32). list shows recorded events; deliveries shows per-peer push delivery state.

Self-capture guard (ADR 0006 no-feedback-loop invariant): a node must not emit routerd.client.ipv4.observed for an address it is itself capturing via a local RemoteAddressClaim, or the delivered capture address would loop back as a fresh observation.

Transport — routerd-eventd

routerd-eventd@<group> is a long-lived per-group daemon (supervised by a generated systemd unit on Linux, rc.d on FreeBSD) that:

  • pushes locally-recorded events to each EventPeer over HTTP, signed with the group HMAC; the receiver verifies the signature and rejects messages outside the replayWindow.
  • records deliveries (per peer, per event) so at-least-once retry is bounded and observable.
  • prunes the local event store per the group retention.

The outbox carries a sourceNode guard so a received event is not re-forwarded back to its origin (no delivery loop).

Subscription → plugin → DynamicConfigPart flow

  1. A node emits an observed fact (routerctl federation event emit, or a future observer).
  2. routerd-eventd delivers it to peers; each peer records it in its event store.
  3. A peer's EventSubscription matches the event and invokes trigger.pluginRef, coalescing per batchWindow / debounce.
  4. The plugin returns a DynamicConfigPart (e.g. a RemoteAddressClaim), which the dynamic-config chain unions into the effective config and reconciles into the dataplane.

This keeps the operator-authored intent declarative: the operator declares the group/peers/subscription; the claims, captures, and action plans are derived.