Skip to main content

spark_connect/
conf.rs

1//! RuntimeConf implementation mirroring `pyspark.sql.conf.RuntimeConfig`.
2//!
3//! Provides runtime configuration management for Spark sessions through
4//! the Spark Connect protocol.
5
6use spark_connect_core::client::SparkConnectClient;
7use spark_connect_core::error::Result;
8use spark_connect_core::runtime::block_on;
9use std::collections::HashMap;
10
11/// Runtime configuration for a Spark session.
12///
13/// Allows getting and setting runtime configuration parameters on the Spark server.
14/// Mirrors `pyspark.sql.conf.RuntimeConfig`.
15pub struct RuntimeConf {
16    /// Shared gRPC client
17    client: std::sync::Arc<SparkConnectClient>,
18}
19
20impl RuntimeConf {
21    /// Create a new RuntimeConf with a client.
22    pub(crate) fn new(client: std::sync::Arc<SparkConnectClient>) -> Self {
23        RuntimeConf { client }
24    }
25
26    /// Set a configuration key-value pair.
27    ///
28    /// Converts boolean and integer values to strings as required by the server.
29    ///
30    /// # Arguments
31    ///
32    /// * `key` - The configuration key (e.g., "spark.sql.shuffle.partitions")
33    /// * `value` - The configuration value as a string, integer, or boolean
34    ///
35    /// # Example
36    ///
37    /// ```ignore
38    /// conf.set("spark.sql.shuffle.partitions", "200")?;
39    /// conf.set("spark.sql.adaptive.enabled", true)?;
40    /// conf.set("spark.sql.maxMetadataStringLength", 100)?;
41    /// ```
42    pub fn set(&self, key: &str, value: &str) -> Result<()> {
43        block_on(self.client.set_config(key, value))
44    }
45
46    /// Get a configuration value by key.
47    ///
48    /// Returns `Ok(None)` if the key does not exist on the server.
49    ///
50    /// # Arguments
51    ///
52    /// * `key` - The configuration key to retrieve
53    ///
54    /// # Example
55    ///
56    /// ```ignore
57    /// let value = conf.get("spark.sql.shuffle.partitions")?;
58    /// println!("Shuffle partitions: {:?}", value);
59    /// ```
60    pub fn get(&self, key: &str) -> Result<Option<String>> {
61        let results = block_on(self.client.get_configs(&[key]))?;
62        Ok(results.into_iter().next().flatten())
63    }
64
65    /// Get a configuration value, returning `default` when the key is unset — instead of
66    /// erroring as `get` does for an unknown key. Uses the server's `GetWithDefault`
67    /// operation, mirroring `RuntimeConfig.get(key, default)`.
68    pub fn get_with_default(&self, key: &str, default: Option<&str>) -> Result<Option<String>> {
69        let results = block_on(self.client.get_config_with_defaults(&[(key, default)]))?;
70        Ok(results.into_iter().next().flatten())
71    }
72
73    /// Get all configuration values as a HashMap.
74    ///
75    /// # Example
76    ///
77    /// ```ignore
78    /// let all_configs = conf.get_all()?;
79    /// for (key, value) in all_configs.iter() {
80    ///     println!("{}: {}", key, value);
81    /// }
82    /// ```
83    pub fn get_all(&self) -> Result<HashMap<String, String>> {
84        let results = block_on(self.client.get_configs_all())?;
85        Ok(results)
86    }
87
88    /// Unset a configuration key (reset to default).
89    ///
90    /// # Arguments
91    ///
92    /// * `key` - The configuration key to unset
93    ///
94    /// # Example
95    ///
96    /// ```ignore
97    /// conf.unset("spark.sql.shuffle.partitions")?;
98    /// ```
99    pub fn unset(&self, key: &str) -> Result<()> {
100        block_on(self.client.unset_config(key))
101    }
102
103    /// Check if a configuration key is modifiable.
104    ///
105    /// Returns `true` if the configuration can be changed at runtime,
106    /// `false` if it's read-only or cannot be modified.
107    ///
108    /// # Arguments
109    ///
110    /// * `key` - The configuration key to check
111    ///
112    /// # Example
113    ///
114    /// ```ignore
115    /// if conf.is_modifiable("spark.sql.shuffle.partitions")? {
116    ///     println!("This config can be modified");
117    /// }
118    /// ```
119    pub fn is_modifiable(&self, key: &str) -> Result<bool> {
120        let results = block_on(self.client.is_config_modifiable(key))?;
121        Ok(results)
122    }
123}
124
125impl Clone for RuntimeConf {
126    fn clone(&self) -> Self {
127        RuntimeConf {
128            client: std::sync::Arc::clone(&self.client),
129        }
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use crate::session::SparkSession;
136
137    fn session() -> SparkSession {
138        SparkSession::builder()
139            .remote("sc://localhost:15002")
140            .get_or_create()
141            .expect("failed to build session")
142    }
143
144    #[test]
145    fn runtime_conf_creation() {
146        let spark = session();
147        let conf = spark.conf();
148        // Verify that conf was created successfully (no network call)
149        let _ = conf.clone();
150    }
151
152    #[test]
153    fn runtime_conf_clone() {
154        let spark = session();
155        let conf1 = spark.conf();
156        let conf2 = conf1.clone();
157        // Both should share the same underlying client
158        let _ = (conf1, conf2);
159    }
160}