Skip to main content

atomr_cluster/
member.rs

1//! Cluster membership types.
2
3use std::cmp::Ordering;
4
5use atomr_core::actor::Address;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum MemberStatus {
10    Joining,
11    WeaklyUp,
12    Up,
13    Leaving,
14    Exiting,
15    Down,
16    Removed,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct Member {
21    pub address: Address,
22    pub up_number: i32,
23    pub status: MemberStatus,
24    pub roles: Vec<String>,
25}
26
27impl Member {
28    pub fn new(address: Address, roles: Vec<String>) -> Self {
29        Self { address, up_number: 0, status: MemberStatus::Joining, roles }
30    }
31
32    pub fn copy_with_status(&self, status: MemberStatus) -> Self {
33        Self { status, ..self.clone() }
34    }
35
36    /// oldest first, then address.
37    /// "Oldest" == lowest `up_number` (joined earliest).
38    pub fn age_ordering(a: &Member, b: &Member) -> Ordering {
39        a.up_number.cmp(&b.up_number).then_with(|| {
40            // Address tie-break: protocol → host → port.
41            a.address
42                .protocol
43                .cmp(&b.address.protocol)
44                .then_with(|| a.address.host.cmp(&b.address.host))
45                .then_with(|| a.address.port.cmp(&b.address.port))
46        })
47    }
48
49    /// Sort `members` in age order in place.
50    pub fn sort_by_age(members: &mut [Member]) {
51        members.sort_by(Self::age_ordering);
52    }
53
54    /// Convenience: the oldest member of a slice (lowest up_number).
55    pub fn oldest(members: &[Member]) -> Option<&Member> {
56        members.iter().min_by(|a, b| Self::age_ordering(a, b))
57    }
58}