use {
crate::{
CreateStreamError,
stream_name::StreamName,
stream_policy::{StreamPolicy, StreamRule},
},
std::sync::{Arc, Weak},
};
pub(super) trait PolicyControlledStream: Send + Sync {
fn stream_name(&self) -> &StreamName;
fn apply_stream_rule(&self, stream_rule: StreamRule) -> Result<(), CreateStreamError>;
}
#[derive(Debug, Default)]
pub(super) struct StreamPolicyManager {
streams: Vec<Weak<dyn PolicyControlledStream>>,
stream_policy: StreamPolicy,
}
impl StreamPolicyManager {
pub(super) fn set_stream_policy(&mut self, new_stream_policy: StreamPolicy) {
self.prune_dead_streams();
self.stream_policy = new_stream_policy;
for stream in self.streams.iter().filter_map(Weak::upgrade) {
let stream_rule = self.stream_policy.stream_rule(stream.stream_name());
let _ = stream.apply_stream_rule(stream_rule);
}
}
pub(super) fn register_new_stream(
&mut self,
stream: Arc<dyn PolicyControlledStream>,
) -> Result<(), CreateStreamError> {
self.prune_dead_streams();
let stream_name_is_in_use = self
.streams
.iter()
.filter_map(Weak::upgrade)
.any(|registered_stream| registered_stream.stream_name() == stream.stream_name());
if stream_name_is_in_use {
return Err(CreateStreamError::StreamNameAlreadyInUse);
}
let stream_rule = self.stream_policy.stream_rule(stream.stream_name());
stream.apply_stream_rule(stream_rule)?;
self.streams.push(Arc::downgrade(&stream));
Ok(())
}
fn prune_dead_streams(&mut self) {
self.streams.retain(|stream| stream.strong_count() > 0);
}
}