durable-actors 0.14.3

Standalone regional durable-actors control plane, host, and durability runtime
use std::collections::BTreeMap;

use super::{LifecycleEvent, LifecycleKind, STALE_AFTER_MS};
use crate::placement::{ActorResidency, ResidencyHistory, ResidencyPeriod};

pub(super) const EVENT_LIMIT: usize = 10_000;

pub(super) fn history(mut events: Vec<LifecycleEvent>, from: u64, to: u64) -> ResidencyHistory {
    let truncated = events.len() > EVENT_LIMIT;
    events.truncate(EVENT_LIMIT);
    let mut instances = BTreeMap::<String, Vec<LifecycleEvent>>::new();
    for event in events {
        instances
            .entry(event.actor.actor_id.clone())
            .or_default()
            .push(event);
    }
    let mut periods = Vec::new();
    for (actor_id, mut events) in instances {
        events.sort_by_key(|event| (event.report.owner_epoch, event.report.sequence));
        events.dedup_by_key(|event| (event.report.owner_epoch, event.report.sequence));
        let mut latest_time = 0;
        events.retain(|event| {
            let ordered = event.report.occurred_at_ms >= latest_time;
            latest_time = latest_time.max(event.report.occurred_at_ms);
            ordered
        });
        for (index, event) in events.iter().enumerate() {
            let start = event.report.occurred_at_ms.max(from);
            let end = events
                .get(index + 1)
                .map_or(to, |next| next.report.occurred_at_ms.min(to));
            let known_until = if event.report.kind == LifecycleKind::Stopped {
                end
            } else {
                event
                    .report
                    .occurred_at_ms
                    .saturating_add(STALE_AFTER_MS)
                    .min(end)
            };
            let status = match (event.report.kind, event.report.resident) {
                (LifecycleKind::Stopped, _) | (_, Some(false)) => ActorResidency::Dormant,
                (_, Some(true)) => ActorResidency::Live,
                _ => ActorResidency::Unknown,
            };
            push(&mut periods, &actor_id, status, start, known_until);
            push(
                &mut periods,
                &actor_id,
                ActorResidency::Unknown,
                start.max(known_until),
                end,
            );
        }
    }
    ResidencyHistory { periods, truncated }
}

fn push(
    periods: &mut Vec<ResidencyPeriod>,
    actor_id: &str,
    status: ActorResidency,
    from_ms: u64,
    to_ms: u64,
) {
    if from_ms >= to_ms {
        return;
    }
    if let Some(previous) = periods.last_mut()
        && previous.actor_id == actor_id
        && previous.status == status
        && previous.to_ms == from_ms
    {
        previous.to_ms = to_ms;
    } else {
        periods.push(ResidencyPeriod {
            actor_id: actor_id.to_owned(),
            status,
            from_ms,
            to_ms,
        });
    }
}