use std::{
collections::BTreeMap,
mem,
sync::{Arc, Mutex},
};
use linera_base::data_types::BlockHeight;
use tokio::sync::oneshot;
use tracing::warn;
#[derive(Clone, Default)]
pub struct DeliveryNotifier {
notifiers: Arc<Mutex<BTreeMap<BlockHeight, Vec<oneshot::Sender<()>>>>>,
}
impl DeliveryNotifier {
pub(super) fn register(&mut self, height: BlockHeight, notifier: oneshot::Sender<()>) {
let mut notifiers = self
.notifiers
.lock()
.expect("Panics should never happen while holding a lock to the `notifiers`");
notifiers.entry(height).or_default().push(notifier);
}
pub(super) fn notify(&mut self, height: BlockHeight) {
let relevant_notifiers = {
let mut notifiers = self
.notifiers
.lock()
.expect("Panics should never happen while holding a lock to the `notifiers`");
let pending_notifiers = height
.try_add_one()
.map(|first_still_undelivered_height| {
notifiers.split_off(&first_still_undelivered_height)
})
.unwrap_or_default();
mem::replace(&mut *notifiers, pending_notifiers)
};
for notifier in relevant_notifiers.into_values().flatten() {
if let Err(()) = notifier.send(()) {
warn!("Failed to notify message delivery to caller");
}
}
}
}