supabase_management_rs/
postgres_configs.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents the configuration settings for a Postgres database.
4///
5/// ```
6/// # use supabase_management_rs::postgres_configs::PostgresConfig;
7///
8/// let mut postgres_config = PostgresConfig::default();
9/// postgres_config.max_parallel_workers = Some(128);
10///
11/// // You can now update your instance's Postgres configuration using Client::set_postgres_config
12/// ```
13#[derive(Debug, Clone, Deserialize, Serialize, Default)]
14pub struct PostgresConfig {
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub effective_cache_size: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub logical_decoding_work_mem: Option<String>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub maintenance_work_mem: Option<String>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub track_activity_query_size: Option<String>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub max_connections: Option<i32>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub max_locks_per_transaction: Option<i32>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub max_parallel_maintenance_workers: Option<i32>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub max_parallel_workers: Option<i32>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub max_parallel_workers_per_gather: Option<i32>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub max_replication_slots: Option<i32>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub max_slot_wal_keep_size: Option<String>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub max_standby_archive_delay: Option<String>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub max_standby_streaming_delay: Option<String>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub max_wal_size: Option<String>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub max_wal_senders: Option<i32>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub max_worker_processes: Option<i32>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub shared_buffers: Option<String>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub statement_timeout: Option<String>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub track_commit_timestamp: Option<bool>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub wal_keep_size: Option<String>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub wal_sender_timeout: Option<String>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub work_mem: Option<String>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub session_replication_role: Option<SessionReplicationRole>,
61}
62
63#[derive(Debug, Clone, Deserialize, Serialize)]
64#[serde(rename_all = "lowercase")]
65pub enum SessionReplicationRole {
66    Origin,
67    Replica,
68    Local,
69}
70
71impl crate::Client {
72    /// Get the Postgres configs for a project
73    pub async fn get_postgres_config(
74        &self,
75        project_id: &str,
76    ) -> Result<PostgresConfig, reqwest::Error> {
77        let url =
78            format!("https://api.supabase.com/v1/projects/{project_id}/config/database/postgres");
79
80        self.client
81            .get(&url)
82            .bearer_auth(&self.api_key)
83            .send()
84            .await?
85            .error_for_status()?
86            .json()
87            .await
88    }
89
90    pub async fn set_postgres_config(
91        &self,
92        project_id: &str,
93        config: &PostgresConfig,
94    ) -> Result<PostgresConfig, reqwest::Error> {
95        let url =
96            format!("https://api.supabase.com/v1/projects/{project_id}/config/database/postgres");
97
98        self.client
99            .put(&url)
100            .bearer_auth(&self.api_key)
101            .json(&config)
102            .send()
103            .await?
104            .error_for_status()?
105            .json()
106            .await
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::PostgresConfig;
113
114    #[test]
115    fn deserializes_pg_config() {
116        let json_data = r#"
117        {
118            "effective_cache_size": "4GB",
119            "logical_decoding_work_mem": "64MB",
120            "maintenance_work_mem": "256MB",
121            "track_activity_query_size": "2048",
122            "max_connections": 100,
123            "max_locks_per_transaction": 128,
124            "max_parallel_maintenance_workers": 2,
125            "max_parallel_workers": 4,
126            "max_parallel_workers_per_gather": 2,
127            "max_replication_slots": 10,
128            "max_slot_wal_keep_size": "1GB",
129            "max_standby_archive_delay": "30s",
130            "max_standby_streaming_delay": "30s",
131            "max_wal_size": "2GB",
132            "max_wal_senders": 5,
133            "max_worker_processes": 8,
134            "shared_buffers": "2GB",
135            "statement_timeout": "60s",
136            "track_commit_timestamp": true,
137            "wal_keep_size": "512MB",
138            "wal_sender_timeout": "60s",
139            "work_mem": "4MB",
140            "session_replication_role": "replica"
141        }
142        "#;
143
144        let config: PostgresConfig =
145            serde_json::from_str(json_data).expect("JSON was not well-formatted");
146    }
147}