robotrt-middleware-core 0.1.0-beta.2

RobotRT modular robotics runtime and middleware components.
Documentation
use std::collections::HashMap;
use std::time::{Duration, Instant};

use super::types::{DiscoveryInactiveReason, DiscoveryPruneReport, DiscoveryState};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum DiscoveryEntryKind {
    Topic,
    Service,
    Mission,
    Endpoint,
}

pub(super) fn increment_prune_report(
    report: &mut DiscoveryPruneReport,
    reason: DiscoveryInactiveReason,
    kind: DiscoveryEntryKind,
) {
    match (reason, kind) {
        (DiscoveryInactiveReason::Expired, DiscoveryEntryKind::Topic) => report.expired_topics += 1,
        (DiscoveryInactiveReason::Expired, DiscoveryEntryKind::Service) => {
            report.expired_services += 1
        }
        (DiscoveryInactiveReason::Expired, DiscoveryEntryKind::Mission) => {
            report.expired_missions += 1
        }
        (DiscoveryInactiveReason::Expired, DiscoveryEntryKind::Endpoint) => {
            report.expired_endpoints += 1
        }
        (DiscoveryInactiveReason::Unhealthy, DiscoveryEntryKind::Topic) => {
            report.unhealthy_topics += 1
        }
        (DiscoveryInactiveReason::Unhealthy, DiscoveryEntryKind::Service) => {
            report.unhealthy_services += 1
        }
        (DiscoveryInactiveReason::Unhealthy, DiscoveryEntryKind::Mission) => {
            report.unhealthy_missions += 1
        }
        (DiscoveryInactiveReason::Unhealthy, DiscoveryEntryKind::Endpoint) => {
            report.unhealthy_endpoints += 1
        }
    }
}

pub(super) fn renew_lease(
    exists: bool,
    states: &mut HashMap<String, DiscoveryState>,
    name: &str,
    ttl: Duration,
) -> bool {
    if !exists {
        return false;
    }
    states.entry(name.to_string()).or_default().refresh_ttl(ttl);
    true
}

pub(super) fn set_health(
    exists: bool,
    states: &mut HashMap<String, DiscoveryState>,
    name: &str,
    healthy: bool,
) -> bool {
    if !exists {
        return false;
    }
    states
        .entry(name.to_string())
        .or_default()
        .set_healthy(healthy);
    true
}

pub(super) fn is_name_active(
    states: &HashMap<String, DiscoveryState>,
    name: &str,
    now: Instant,
) -> bool {
    states
        .get(name)
        .map(|state| state.is_active(now))
        .unwrap_or(true)
}

pub(super) fn collect_inactive_names<'a, I>(
    names: I,
    states: &HashMap<String, DiscoveryState>,
    now: Instant,
) -> Vec<(String, DiscoveryInactiveReason)>
where
    I: IntoIterator<Item = &'a String>,
{
    names
        .into_iter()
        .filter_map(|name| {
            states
                .get(name)
                .and_then(|state| state.inactive_reason(now))
                .map(|reason| (name.clone(), reason))
        })
        .collect()
}

pub(super) fn active_count<'a, I>(
    names: I,
    states: &HashMap<String, DiscoveryState>,
    now: Instant,
) -> usize
where
    I: IntoIterator<Item = &'a String>,
{
    names
        .into_iter()
        .filter(|name| is_name_active(states, name, now))
        .count()
}

pub(super) fn inactive_count<'a, I>(
    names: I,
    states: &HashMap<String, DiscoveryState>,
    now: Instant,
    reason: DiscoveryInactiveReason,
) -> usize
where
    I: IntoIterator<Item = &'a String>,
{
    names
        .into_iter()
        .filter(|name| {
            states
                .get(*name)
                .and_then(|state| state.inactive_reason(now))
                .is_some_and(|found| found == reason)
        })
        .count()
}