use reliar_core::{MessageType, SettingsError};
use crate::settings::{MessageTypeNames, OutboxSettings};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OutboxPolicy {
enabled: bool,
allowed: MessageTypeNames,
disallowed: MessageTypeNames,
}
impl Default for OutboxPolicy {
fn default() -> Self {
Self {
enabled: true,
allowed: MessageTypeNames::empty(),
disallowed: MessageTypeNames::empty(),
}
}
}
impl OutboxPolicy {
pub fn from_settings(settings: &OutboxSettings) -> Result<Self, SettingsError> {
check_disjoint(
"disallowed_types",
&settings.allowed_types,
&settings.disallowed_types,
)?;
Ok(Self {
enabled: settings.enabled,
allowed: settings.allowed_types.clone(),
disallowed: settings.disallowed_types.clone(),
})
}
#[must_use]
pub fn decide(&self, message_type: &MessageType) -> RouteKind {
let name = message_type.name();
if !self.enabled {
return RouteKind::Direct;
}
if self.disallowed.contains(name) {
return RouteKind::Direct;
}
if self.allowed.is_empty() {
return RouteKind::Outbox;
}
if self.allowed.contains(name) {
return RouteKind::Outbox;
}
RouteKind::Direct
}
#[must_use]
pub const fn enabled(&self) -> bool {
self.enabled
}
#[must_use]
pub fn allowed_types(&self) -> &MessageTypeNames {
&self.allowed
}
#[must_use]
pub fn disallowed_types(&self) -> &MessageTypeNames {
&self.disallowed
}
}
pub(crate) fn check_disjoint(
key: &str,
allowed: &MessageTypeNames,
disallowed: &MessageTypeNames,
) -> Result<(), SettingsError> {
if allowed.names().iter().any(|name| disallowed.contains(name)) {
return Err(SettingsError::out_of_range(
key.to_string(),
"a message type may not appear in both allowed_types and disallowed_types",
));
}
Ok(())
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum RouteKind {
Outbox,
Direct,
}
impl RouteKind {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Outbox => "outbox",
Self::Direct => "direct",
}
}
#[must_use]
pub const fn is_outbox(self) -> bool {
matches!(self, Self::Outbox)
}
}