use std::collections::BTreeSet;
use serde::{Deserialize, Serialize};
use super::super::capability::Capability;
use super::super::memory::MemoryDemand;
use super::spec::WorkloadSpec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TrustTier {
Discovered,
Paired,
Pinned,
}
impl TrustTier {
pub fn as_str(self) -> &'static str {
match self {
TrustTier::Discovered => "discovered",
TrustTier::Paired => "paired",
TrustTier::Pinned => "pinned",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Liveness {
Alive,
Suspect,
Dead,
Unknown,
}
impl Liveness {
pub fn as_str(self) -> &'static str {
match self {
Liveness::Alive => "alive",
Liveness::Suspect => "suspect",
Liveness::Dead => "dead",
Liveness::Unknown => "unknown",
}
}
}
pub trait PlacementFacts {
fn node_id(&self) -> &str;
fn capabilities(&self) -> &[Capability];
fn liveness(&self) -> Liveness;
fn trust_tier(&self) -> TrustTier;
fn facts_expire_at_ms(&self) -> Option<u64>;
fn load(&self) -> Option<f64> {
None
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct WorkloadRef {
pub kind: String,
pub name: String,
}
impl WorkloadRef {
pub fn of(spec: &WorkloadSpec) -> Self {
Self {
kind: spec.kind.clone(),
name: spec.name.clone(),
}
}
pub fn is(&self, spec: &WorkloadSpec) -> bool {
*self == Self::of(spec)
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct InstanceRecord {
pub node_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workload: Option<WorkloadRef>,
#[serde(default)]
pub labels: Vec<String>,
#[serde(default)]
pub excludes: Vec<String>,
#[serde(default)]
pub pending: MemoryDemand,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct ClusterState {
pub now_ms: u64,
#[serde(default)]
pub revoked_nodes: BTreeSet<String>,
#[serde(default)]
pub revoked_refs: BTreeSet<String>,
#[serde(default)]
pub instances: Vec<InstanceRecord>,
}
impl ClusterState {
pub fn neighbours_on<'a>(
&'a self,
node_id: &'a str,
spec: &'a WorkloadSpec,
) -> impl Iterator<Item = &'a InstanceRecord> {
self.instances_on(node_id)
.filter(move |i| !i.workload.as_ref().is_some_and(|w| w.is(spec)))
}
pub fn instances_on<'a>(
&'a self,
node_id: &'a str,
) -> impl Iterator<Item = &'a InstanceRecord> {
self.instances.iter().filter(move |i| i.node_id == node_id)
}
}