faucet_sink_mongodb/
config.rs1use faucet_core::DEFAULT_BATCH_SIZE;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Clone, Serialize, Deserialize, JsonSchema)]
23pub struct MongoSinkConfig {
24 pub connection_uri: String,
26 pub database: String,
28 pub collection: String,
30 #[serde(default = "default_batch_size")]
45 pub batch_size: usize,
46 #[serde(default)]
55 pub ordered: bool,
56 #[serde(flatten)]
64 pub write: faucet_core::WriteSpec,
65}
66
67fn default_batch_size() -> usize {
68 DEFAULT_BATCH_SIZE
69}
70
71impl MongoSinkConfig {
72 pub fn new(
74 connection_uri: impl Into<String>,
75 database: impl Into<String>,
76 collection: impl Into<String>,
77 ) -> Self {
78 Self {
79 connection_uri: connection_uri.into(),
80 database: database.into(),
81 collection: collection.into(),
82 batch_size: DEFAULT_BATCH_SIZE,
83 ordered: false,
84 write: faucet_core::WriteSpec::default(),
85 }
86 }
87
88 pub fn with_ordered(mut self, ordered: bool) -> Self {
90 self.ordered = ordered;
91 self
92 }
93
94 pub fn with_batch_size(mut self, batch_size: usize) -> Self {
100 self.batch_size = batch_size;
101 self
102 }
103}
104
105impl fmt::Debug for MongoSinkConfig {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.debug_struct("MongoSinkConfig")
108 .field("connection_uri", &"***")
109 .field("database", &self.database)
110 .field("collection", &self.collection)
111 .field("batch_size", &self.batch_size)
112 .field("ordered", &self.ordered)
113 .field("write", &self.write)
114 .finish()
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn default_config() {
124 let config = MongoSinkConfig::new("mongodb://localhost:27017", "testdb", "users");
125 assert_eq!(config.database, "testdb");
126 assert_eq!(config.collection, "users");
127 assert_eq!(config.batch_size, DEFAULT_BATCH_SIZE);
128 }
129
130 #[test]
131 fn batch_size_defaults_to_default_batch_size() {
132 let config = MongoSinkConfig::new("mongodb://localhost:27017", "testdb", "users");
133 assert_eq!(config.batch_size, faucet_core::DEFAULT_BATCH_SIZE);
134 }
135
136 #[test]
137 fn with_batch_size_overrides_default() {
138 let config = MongoSinkConfig::new("mongodb://localhost:27017", "testdb", "users")
139 .with_batch_size(2000);
140 assert_eq!(config.batch_size, 2000);
141 }
142
143 #[test]
144 fn debug_masks_connection_uri() {
145 let config = MongoSinkConfig::new("mongodb://user:secret@host:27017/db", "testdb", "users");
146 let debug = format!("{config:?}");
147 assert!(debug.contains("***"));
148 assert!(!debug.contains("secret"));
149 }
150
151 #[test]
152 fn batch_size_zero_is_accepted_as_no_batching_sentinel() {
153 let config =
154 MongoSinkConfig::new("mongodb://localhost:27017", "db", "c").with_batch_size(0);
155 assert_eq!(config.batch_size, 0);
156 assert!(faucet_core::validate_batch_size(config.batch_size).is_ok());
157 }
158
159 #[test]
160 fn batch_size_above_max_is_rejected_by_validate_batch_size() {
161 let config = MongoSinkConfig::new("mongodb://localhost:27017", "db", "c")
162 .with_batch_size(faucet_core::MAX_BATCH_SIZE + 1);
163 assert!(faucet_core::validate_batch_size(config.batch_size).is_err());
164 }
165
166 #[test]
167 fn batch_size_deserializes_from_json() {
168 let json = r#"{
169 "connection_uri": "mongodb://localhost:27017",
170 "database": "db",
171 "collection": "c",
172 "batch_size": 250
173 }"#;
174 let config: MongoSinkConfig = serde_json::from_str(json).unwrap();
175 assert_eq!(config.batch_size, 250);
176 }
177
178 #[test]
179 fn batch_size_defaults_when_absent_in_json() {
180 let json = r#"{
181 "connection_uri": "mongodb://localhost:27017",
182 "database": "db",
183 "collection": "c"
184 }"#;
185 let config: MongoSinkConfig = serde_json::from_str(json).unwrap();
186 assert_eq!(config.batch_size, faucet_core::DEFAULT_BATCH_SIZE);
187 }
188}