use super::*;
use crate::nut::{iac::publish::BroadcastInfo, Nut, IMPOSSIBLE_ERR_MSG};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[non_exhaustive]
pub enum LifecycleStatus {
Active,
Inactive,
Deleted,
}
pub(crate) struct LifecycleChange {
activity: UncheckedActivityId,
status: LifecycleStatus,
}
impl LifecycleStatus {
pub fn is_active(&self) -> bool {
match self {
Self::Active => true,
Self::Inactive => false,
Self::Deleted => false,
}
}
}
impl Nut {
pub(crate) fn set_status(&self, id: UncheckedActivityId, status: LifecycleStatus) {
let event = LifecycleChange {
activity: id,
status,
};
self.deferred_events.push(event.into());
self.catch_up_deferred_to_quiescence();
}
pub(crate) fn unchecked_lifecycle_change(&self, lifecycle_change: &LifecycleChange) {
let before = self
.activities
.try_borrow()
.expect(IMPOSSIBLE_ERR_MSG)
.status(lifecycle_change.activity);
if before != lifecycle_change.status {
assert_ne!(
before,
LifecycleStatus::Deleted,
"Attempted to set activity {} status after it has been deleted.",
lifecycle_change.activity.index
);
self.activities
.try_borrow_mut()
.expect(IMPOSSIBLE_ERR_MSG)
.set_status(lifecycle_change.activity, lifecycle_change.status);
if !before.is_active() && lifecycle_change.status.is_active() {
self.broadcast(BroadcastInfo::local(
(),
lifecycle_change.activity,
Topic::enter(),
));
} else if before.is_active() && !lifecycle_change.status.is_active() {
self.broadcast(BroadcastInfo::local(
(),
lifecycle_change.activity,
Topic::leave(),
));
}
}
if lifecycle_change.status == LifecycleStatus::Deleted {
self.deferred_events
.push(nut::exec::Deferred::RemoveActivity(
lifecycle_change.activity,
));
}
}
pub(crate) fn delete_activity(&self, id: UncheckedActivityId) {
self.activities
.try_borrow_mut()
.expect(IMPOSSIBLE_ERR_MSG)
.delete(
id,
&mut self
.managed_state
.try_borrow_mut()
.expect(IMPOSSIBLE_ERR_MSG),
);
}
}
#[cfg(debug_assertions)]
impl std::fmt::Debug for LifecycleChange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Transition to state: {:?}", self.status)
}
}