use super::*;
impl OperationManager {
pub async fn unregister(&self, id: &str) -> Result<()> {
self.unregister_selected(id, None).await
}
pub async fn unregister_from(&self, owner: &str, id: &str) -> Result<()> {
self.unregister_selected(id, Some(owner)).await
}
pub(super) async fn unregister_selected(&self, id: &str, owner: Option<&str>) -> Result<()> {
let entry = {
let state = self.registry.state.lock().expect("operation registry lock is healthy");
Arc::clone(state.select(id, owner)?)
};
#[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
if let Some(scope) = &entry.plugin {
scope.unbind_operations();
}
let retired = {
let mut state = self.registry.state.lock().expect("operation registry lock is healthy");
if !state.owned(id, entry.owner.as_str()).is_some_and(|current| Arc::ptr_eq(current, &entry)) {
return Err(Error::NotRegistered { domain: "operation", name: id.to_owned() });
}
let _pending = entry.pending.lock().expect("operation settlement lock is healthy");
entry.retirement.store(Retirement::Explicit as u8, Ordering::Release);
entry.active.store(false, Ordering::Release);
let retired = state.remove_cache(|cached| !cached.target.upgrade().is_some_and(|target| !Arc::ptr_eq(&target, &entry)));
drop(_pending);
retired
};
drop(retired);
settle(&entry).await?;
let mut state = self.registry.state.lock().expect("operation registry lock is healthy");
if state.owned(id, entry.owner.as_str()).is_some_and(|current| Arc::ptr_eq(current, &entry)) {
state.remove_owned(id, entry.owner.as_str());
}
Ok(())
}
#[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
pub(in crate::operations) fn fence(&self, entries: &[Arc<Entry>], abandoned: bool) {
let retired = {
let mut state = self.registry.state.lock().expect("operation registry lock is healthy");
for entry in entries {
let _pending = entry.pending.lock().expect("operation settlement lock is healthy");
let _ = entry.retirement.try_update(Ordering::AcqRel, Ordering::Acquire, |state| {
(state != Retirement::Explicit as u8).then_some(if abandoned {
Retirement::Abandoned as u8
} else {
Retirement::Retained as u8
})
});
entry.active.store(false, Ordering::Release);
}
state.remove_cache(|cached| {
cached.target.upgrade().is_some_and(|target| entries.iter().any(|entry| Arc::ptr_eq(&target, entry)))
})
};
drop(retired);
}
#[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
pub(in crate::operations) fn remove_settled(&self, entries: &[Arc<Entry>]) {
let mut state = self.registry.state.lock().expect("operation registry lock is healthy");
for entry in entries {
if entry.settled() && state.owned(entry.id(), entry.owner.as_str()).is_some_and(|current| Arc::ptr_eq(current, entry)) {
state.remove_owned(entry.id(), entry.owner.as_str());
}
}
}
#[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
pub(in crate::operations) async fn settle_entries(&self, entries: &[Arc<Entry>]) -> Result<()> {
self.settle_owned_entries(entries).await?;
self.remove_settled(entries);
Ok(())
}
#[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
pub(in crate::operations) async fn settle_owned_entries(&self, entries: &[Arc<Entry>]) -> Result<()> {
for entry in entries {
settle(entry).await?;
}
Ok(())
}
}