cat_gateway/settings/
cassandra_db.rs

1//! Command line and environment variable settings for the service
2
3use tracing::info;
4
5use super::str_env_var::StringEnvVar;
6use crate::db::{
7    self,
8    index::session::{CompressionChoice, TlsChoice},
9};
10
11/// Default Cassandra DB URL for the Persistent DB.
12pub(super) const PERSISTENT_URL_DEFAULT: &str = "127.0.0.1:9042";
13
14/// Default Cassandra DB URL for the Persistent DB.
15pub(super) const PERSISTENT_NAMESPACE_DEFAULT: &str = "persistent";
16
17/// Default Cassandra DB URL for the Persistent DB.
18pub(super) const VOLATILE_URL_DEFAULT: &str = "127.0.0.1:9042";
19
20/// Default Cassandra DB URL for the Persistent DB.
21pub(super) const VOLATILE_NAMESPACE_DEFAULT: &str = "volatile";
22
23/// Default maximum batch size.
24/// This comes from:
25/// <https://docs.aws.amazon.com/keyspaces/latest/devguide/functional-differences.html#functional-differences.batch>
26/// Scylla may support larger batches for better performance.
27/// Larger batches will incur more memory overhead to store the prepared batches.
28const MAX_BATCH_SIZE_DEFAULT: i64 = 30;
29
30/// Minimum possible batch size.
31pub(crate) const MIN_BATCH_SIZE: i64 = 1;
32
33/// Maximum possible batch size.
34const MAX_BATCH_SIZE: i64 = 256;
35
36/// Configuration for an individual cassandra cluster.
37#[derive(Clone)]
38pub(crate) struct EnvVars {
39    /// The Address/s of the DB.
40    pub(crate) url: StringEnvVar,
41
42    /// The Namespace of Cassandra DB.
43    pub(crate) namespace: StringEnvVar,
44
45    /// The `UserName` to use for the Cassandra DB.
46    pub(crate) username: Option<StringEnvVar>,
47
48    /// The Password to use for the Cassandra DB..
49    pub(crate) password: Option<StringEnvVar>,
50
51    /// Use TLS for the connection?
52    pub(crate) tls: TlsChoice,
53
54    /// Use TLS for the connection?
55    pub(crate) tls_cert: Option<StringEnvVar>,
56
57    /// Compression to use.
58    pub(crate) compression: CompressionChoice,
59
60    /// Maximum Configured Batch size.
61    pub(crate) max_batch_size: i64,
62
63    /// Config options for deployment i.e replication strategy
64    pub(crate) deployment: StringEnvVar,
65}
66
67impl EnvVars {
68    /// Create a config for a cassandra cluster, identified by a default namespace.
69    pub(super) fn new(url: &str, namespace: &str) -> Self {
70        let name = namespace.to_uppercase();
71
72        // We can actually change the namespace, but can't change the name used for env vars.
73        let namespace = StringEnvVar::new(&format!("CASSANDRA_{name}_NAMESPACE"), namespace.into());
74
75        let tls =
76            StringEnvVar::new_as_enum(&format!("CASSANDRA_{name}_TLS"), TlsChoice::Disabled, false);
77        let compression = StringEnvVar::new_as_enum(
78            &format!("CASSANDRA_{name}_COMPRESSION"),
79            CompressionChoice::Lz4,
80            false,
81        );
82
83        Self {
84            url: StringEnvVar::new(&format!("CASSANDRA_{name}_URL"), url.into()),
85            namespace,
86            username: StringEnvVar::new_optional(&format!("CASSANDRA_{name}_USERNAME"), false),
87            password: StringEnvVar::new_optional(&format!("CASSANDRA_{name}_PASSWORD"), true),
88            tls,
89            tls_cert: StringEnvVar::new_optional(&format!("CASSANDRA_{name}_TLS_CERT"), false),
90            compression,
91            max_batch_size: StringEnvVar::new_as_int(
92                &format!("CASSANDRA_{name}_BATCH_SIZE"),
93                MAX_BATCH_SIZE_DEFAULT,
94                MIN_BATCH_SIZE,
95                MAX_BATCH_SIZE,
96            ),
97            deployment: StringEnvVar::new(
98                &format!("CASSANDRA_{name}_DEPLOYMENT"),
99                "{'class': 'NetworkTopologyStrategy','replication_factor': 1}".into(),
100            ),
101        }
102    }
103
104    /// Log the configuration of this Cassandra DB
105    pub(crate) fn log(&self, persistent: bool) {
106        let db_type = if persistent { "Persistent" } else { "Volatile" };
107
108        let auth = match (&self.username, &self.password) {
109            (Some(u), Some(_)) => format!("Username: {} Password: REDACTED", u.as_str()),
110            _ => "No Authentication".to_string(),
111        };
112
113        let tls_cert = match &self.tls_cert {
114            None => "No TLS Certificate Defined".to_string(),
115            Some(cert) => cert.as_string(),
116        };
117
118        info!(
119            url = self.url.as_str(),
120            namespace = db::index::schema::namespace(self),
121            auth = auth,
122            tls = self.tls.to_string(),
123            cert = tls_cert,
124            compression = self.compression.to_string(),
125            "Cassandra {db_type} DB Configuration"
126        );
127    }
128}