Skip to main content

greentic_pack/
events.rs

1use std::collections::BTreeSet;
2use std::fmt;
3
4use anyhow::{Result, bail};
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Default)]
9pub struct EventsSection {
10    #[serde(default)]
11    pub providers: Vec<EventProviderSpec>,
12}
13
14impl EventsSection {
15    pub fn validate(&self) -> Result<()> {
16        let mut seen = BTreeSet::new();
17        for provider in &self.providers {
18            provider.validate()?;
19            if !seen.insert(provider.name.clone()) {
20                bail!("duplicate events provider name: {}", provider.name);
21            }
22        }
23        Ok(())
24    }
25}
26
27#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
28pub struct EventProviderSpec {
29    pub name: String,
30    pub kind: EventProviderKind,
31    pub component: String,
32    #[serde(default, skip_serializing_if = "Option::is_none")]
33    pub default_flow: Option<String>,
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub custom_flow: Option<String>,
36    #[serde(default)]
37    pub capabilities: EventProviderCapabilities,
38}
39
40impl EventProviderSpec {
41    fn validate(&self) -> Result<()> {
42        if self.name.trim().is_empty() {
43            bail!("events.providers[].name is required");
44        }
45        if self.component.trim().is_empty() {
46            bail!(
47                "events.providers[{}].component must not be empty",
48                self.name
49            );
50        }
51        for topic in &self.capabilities.topics {
52            if topic.trim().is_empty() {
53                bail!(
54                    "events.providers[{}].capabilities.topics may not contain empty entries",
55                    self.name
56                );
57            }
58        }
59        Ok(())
60    }
61}
62
63#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Default)]
64pub struct EventProviderCapabilities {
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub transport: Option<TransportKind>,
67    #[serde(default, skip_serializing_if = "Option::is_none")]
68    pub reliability: Option<ReliabilityKind>,
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub ordering: Option<OrderingKind>,
71    #[serde(default, skip_serializing_if = "Vec::is_empty")]
72    pub topics: Vec<String>,
73}
74
75#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
76#[serde(rename_all = "snake_case")]
77pub enum EventProviderKind {
78    Broker,
79    Source,
80    Sink,
81    Bridge,
82}
83
84impl fmt::Display for EventProviderKind {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        let value = match self {
87            Self::Broker => "broker",
88            Self::Source => "source",
89            Self::Sink => "sink",
90            Self::Bridge => "bridge",
91        };
92        f.write_str(value)
93    }
94}
95
96#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
97#[serde(rename_all = "snake_case")]
98#[serde(untagged)]
99pub enum TransportKind {
100    Nats,
101    Kafka,
102    Sqs,
103    Webhook,
104    Email,
105    Other(String),
106}
107
108impl fmt::Display for TransportKind {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        match self {
111            Self::Nats => f.write_str("nats"),
112            Self::Kafka => f.write_str("kafka"),
113            Self::Sqs => f.write_str("sqs"),
114            Self::Webhook => f.write_str("webhook"),
115            Self::Email => f.write_str("email"),
116            Self::Other(value) => f.write_str(value),
117        }
118    }
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
122#[serde(rename_all = "snake_case")]
123pub enum ReliabilityKind {
124    AtMostOnce,
125    AtLeastOnce,
126    EffectivelyOnce,
127}
128
129impl fmt::Display for ReliabilityKind {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        let value = match self {
132            Self::AtMostOnce => "at_most_once",
133            Self::AtLeastOnce => "at_least_once",
134            Self::EffectivelyOnce => "effectively_once",
135        };
136        f.write_str(value)
137    }
138}
139
140#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
141#[serde(rename_all = "snake_case")]
142pub enum OrderingKind {
143    None,
144    PerKey,
145    Global,
146}
147
148impl fmt::Display for OrderingKind {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        let value = match self {
151            Self::None => "none",
152            Self::PerKey => "per_key",
153            Self::Global => "global",
154        };
155        f.write_str(value)
156    }
157}