arcly_stream/cluster.rs
1//! Multi-node clustering contracts: origin/edge discovery and stream relay.
2//!
3//! These are **contracts only** — the engine defines the seams an edge tier
4//! plugs into, but ships no concrete discovery or transport (those depend on the
5//! deployment's service mesh / gossip / control plane). An edge node implements
6//! [`ClusterRelay`] to locate a stream's origin, pull it locally, and announce
7//! the streams it serves.
8
9use crate::{Result, StreamKey};
10use async_trait::async_trait;
11
12/// Address of a node in the cluster (opaque to the engine).
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct NodeAddr(pub String);
15
16impl<T: Into<String>> From<T> for NodeAddr {
17 fn from(s: T) -> Self {
18 NodeAddr(s.into())
19 }
20}
21
22/// Origin/edge relay contract. Implement to federate streams across nodes:
23/// an edge that lacks a stream locally [`locate`](Self::locate)s its origin and
24/// [`pull`](Self::pull)s it; an origin [`announce`](Self::announce)s what it has.
25#[async_trait]
26pub trait ClusterRelay: Send + Sync + 'static {
27 /// Find a node currently serving `key`, if any (e.g. via the control plane).
28 async fn locate(&self, key: &StreamKey) -> Result<Option<NodeAddr>>;
29
30 /// Begin relaying `key` from `origin` into the local engine, returning once
31 /// the local mirror is publishing.
32 async fn pull(&self, key: &StreamKey, origin: &NodeAddr) -> Result<()>;
33
34 /// Advertise that this node serves `key` so edges can discover it.
35 async fn announce(&self, key: &StreamKey) -> Result<()>;
36
37 /// Withdraw a previous [`announce`](Self::announce) when the stream ends.
38 async fn withdraw(&self, key: &StreamKey) -> Result<()>;
39}