1use std::sync::Arc;
9
10use crate::config::RuntimeConfig;
11use crate::sinks::SinkDispatcher;
12use crate::types::{first_delivery_error, ListChannelsOutput, VentEvent, VentOutput};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct VentRequest {
17 pub message: String,
18 pub channel: Option<String>,
19}
20
21#[derive(Clone)]
23pub struct VentService {
24 config: Arc<RuntimeConfig>,
25 dispatcher: SinkDispatcher,
26 project: Arc<String>,
27}
28
29impl VentService {
30 #[must_use]
32 pub fn new(config: RuntimeConfig, project: String) -> Self {
33 let dispatcher = SinkDispatcher::new(Arc::new(config));
34 let config = dispatcher.config();
35 Self {
36 config,
37 dispatcher,
38 project: Arc::new(project),
39 }
40 }
41
42 #[must_use]
43 pub(crate) fn config(&self) -> &RuntimeConfig {
44 &self.config
45 }
46
47 #[must_use]
49 pub fn list_channels(&self) -> ListChannelsOutput {
50 self.config.channel_list()
51 }
52
53 pub async fn send(&self, request: VentRequest) -> VentOutput {
55 let message = request.message.trim();
56 if message.is_empty() {
57 return failure_output(
58 self.config.default_channel().to_string(),
59 "message must not be empty".to_string(),
60 );
61 }
62
63 let channel = request
64 .channel
65 .as_deref()
66 .map(str::trim)
67 .filter(|channel| !channel.is_empty())
68 .unwrap_or_else(|| self.config.default_channel());
69
70 if !self.config.has_channel(channel) {
71 return failure_output(channel.to_string(), format!("unknown channel: {channel}"));
72 }
73
74 let event = VentEvent::new(
75 channel.to_string(),
76 message.to_string(),
77 self.project.as_ref().clone(),
78 );
79 let statuses = self.dispatcher.dispatch(&event).await;
80 let ok = statuses.iter().all(|status| status.ok);
81
82 VentOutput {
83 ok,
84 event_id: event.id.to_string(),
85 channel: event.channel,
86 error: first_delivery_error(&statuses),
87 }
88 }
89}
90
91fn failure_output(channel: String, message: String) -> VentOutput {
92 VentOutput {
93 ok: false,
94 event_id: String::new(),
95 channel,
96 error: Some(message),
97 }
98}