use std::sync::Arc;
use super::block::registry::RegistrationHandle;
pub trait EventManager: EventPublisher + EventReleaseManager + Send + Sync {
}
pub trait EventPublisher: Send + Sync {
fn publish(&self, handles: Vec<Arc<RegistrationHandle>>);
}
pub trait EventReleaseManager: Send + Sync {
fn block_release(&self, registration_handle: &RegistrationHandle);
}
pub struct PublishHandle {
handle: Arc<RegistrationHandle>,
publisher: Option<Arc<dyn EventPublisher>>,
}
impl PublishHandle {
pub fn new(handle: RegistrationHandle, publisher: Arc<dyn EventPublisher>) -> Self {
let handle = Arc::new(handle);
let publisher = Some(publisher);
Self { handle, publisher }
}
pub fn remove_handle(&self) -> Arc<RegistrationHandle> {
self.handle.clone()
}
fn disarm(&mut self) {
self.publisher = None;
}
}
impl Drop for PublishHandle {
fn drop(&mut self) {
if let Some(publisher) = self.publisher.take() {
publisher.publish(vec![self.handle.clone()]);
}
}
}
#[derive(Clone)]
pub struct Publisher {
handles: Vec<Arc<RegistrationHandle>>,
publisher: Arc<dyn EventPublisher>,
}
impl Publisher {
pub fn new(publisher: Arc<dyn EventPublisher>) -> Self {
Self {
handles: Vec::new(),
publisher,
}
}
pub fn take_handle(&mut self, publish_handle: PublishHandle) -> Arc<RegistrationHandle> {
let handle = publish_handle.remove_handle();
self.handles.push(handle.clone());
let mut publish_handle = publish_handle;
publish_handle.disarm();
handle
}
pub fn publish(&mut self) {
let handles = std::mem::take(&mut self.handles);
if !handles.is_empty() {
self.publisher.publish(handles);
}
}
}
impl Drop for Publisher {
fn drop(&mut self) {
self.publish();
}
}
pub struct NullEventManager;
impl NullEventManager {
pub fn new() -> Arc<Self> {
Arc::new(Self {})
}
}
impl EventManager for NullEventManager {}
impl EventPublisher for NullEventManager {
fn publish(&self, _handles: Vec<Arc<RegistrationHandle>>) {}
}
impl EventReleaseManager for NullEventManager {
fn block_release(&self, _registration_handle: &RegistrationHandle) {}
}
#[cfg(test)]
pub mod tests {
use crate::tokens::SequenceHash;
use super::*;
#[derive(Debug, PartialEq, Eq)]
pub enum EventType {
Register(SequenceHash),
Remove(SequenceHash),
}
pub struct MockEventManager {
tx: tokio::sync::mpsc::UnboundedSender<Vec<EventType>>,
}
impl MockEventManager {
pub fn new() -> (
Arc<Self>,
tokio::sync::mpsc::UnboundedReceiver<Vec<EventType>>,
) {
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
(Arc::new(Self { tx }), rx)
}
pub fn publisher(self: &Arc<Self>) -> Publisher {
Publisher::new(self.clone())
}
}
impl EventManager for MockEventManager {}
impl EventPublisher for MockEventManager {
fn publish(&self, handles: Vec<Arc<RegistrationHandle>>) {
let events = handles
.iter()
.map(|handle| EventType::Register(handle.sequence_hash()))
.collect::<Vec<_>>();
self.tx.send(events).unwrap();
}
}
impl EventReleaseManager for MockEventManager {
fn block_release(&self, registration_handle: &RegistrationHandle) {
let events = vec![EventType::Remove(registration_handle.sequence_hash())];
self.tx.send(events).unwrap();
}
}
}