rocket_sync_db_pools_community/
config.rs

1use rocket::figment::{self, providers::Serialized, Figment};
2use rocket::{Build, Rocket};
3
4use serde::{Deserialize, Serialize};
5
6/// A base `Config` for any `Poolable` type.
7///
8/// For the following configuration:
9///
10/// ```toml
11/// [global.databases.my_database]
12/// url = "postgres://root:root@localhost/my_database"
13/// pool_size = 10
14/// timeout = 5
15/// ```
16///
17/// ...`Config::from("my_database", rocket)` would return the following struct:
18///
19/// ```rust
20/// # extern crate rocket_sync_db_pools_community as rocket_sync_db_pools;
21/// # use rocket_sync_db_pools::Config;
22/// Config {
23///     url: "postgres://root:root@localhost/my_database".into(),
24///     pool_size: 10,
25///     timeout: 5
26/// };
27/// ```
28///
29/// If you want to implement your own custom database adapter (or other
30/// database-like struct that can be pooled by `r2d2`) and need some more
31/// configurations options, you may need to define a custom `Config` struct.
32/// Note, however, that the configuration values in `Config` are required.
33#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
34pub struct Config {
35    /// Connection URL specified in the Rocket configuration.
36    pub url: String,
37    /// Initial pool size. Defaults to the number of Rocket workers * 4.
38    pub pool_size: u32,
39    /// How long to wait, in seconds, for a new connection before timing out.
40    /// Defaults to `5`.
41    // FIXME: Use `time`.
42    pub timeout: u8,
43}
44
45impl Config {
46    /// Retrieves the database configuration for the database named `name`.
47    ///
48    /// This function is primarily used by the generated code from the
49    /// `#[database]` attribute.
50    ///
51    /// # Example
52    ///
53    /// ```rust
54    /// # extern crate rocket_sync_db_pools_community as rocket_sync_db_pools;
55    /// # #[cfg(feature = "diesel_sqlite_pool")] {
56    /// # use rocket::figment::{Figment, providers::{Format, Toml}};
57    /// // Assume that these are the contents of `Rocket.toml`:
58    /// # let toml = Toml::string(r#"
59    /// [default.databases]
60    /// my_db = { url = "db/db.sqlite", pool_size = 25 }
61    /// my_other_db = { url = "mysql://root:root@localhost/database" }
62    /// # "#).nested();
63    ///
64    /// use rocket::{Rocket, Build};
65    /// use rocket_sync_db_pools::Config;
66    ///
67    /// fn pool(rocket: &Rocket<Build>) {
68    ///     let config = Config::from("my_db", rocket).unwrap();
69    ///     assert_eq!(config.url, "db/db.sqlite");
70    ///     assert_eq!(config.pool_size, 25);
71    ///
72    ///     let config = Config::from("my_other_db", rocket).unwrap();
73    ///     assert_eq!(config.url, "mysql://root:root@localhost/database");
74    ///
75    ///     let workers = rocket.figment().extract_inner::<u32>(rocket::Config::WORKERS);
76    ///     assert_eq!(config.pool_size, (workers.unwrap() * 4));
77    ///
78    ///     let config = Config::from("unknown_db", rocket);
79    ///     assert!(config.is_err())
80    /// }
81    /// #
82    /// # let config = Figment::from(rocket::Config::default()).merge(toml);
83    /// # let rocket = rocket::custom(config);
84    /// # pool(&rocket);
85    /// # }
86    /// ```
87    #[allow(clippy::result_large_err)]
88    pub fn from(db_name: &str, rocket: &Rocket<Build>) -> Result<Config, figment::Error> {
89        Config::figment(db_name, rocket).extract::<Self>()
90    }
91
92    /// Returns a `Figment` focused on the configuration for the database with
93    /// name `db_name`.
94    ///
95    /// # Example
96    ///
97    /// ```rust
98    /// # extern crate rocket_sync_db_pools_community as rocket_sync_db_pools;
99    /// use rocket::{Rocket, Build};
100    /// use rocket_sync_db_pools::Config;
101    ///
102    /// fn pool(rocket: &Rocket<Build>) {
103    ///     let my_db_figment = Config::figment("my_db", rocket);
104    ///     let mysql_prod_figment = Config::figment("mysql_prod", rocket);
105    /// }
106    /// ```
107    pub fn figment(db_name: &str, rocket: &Rocket<Build>) -> Figment {
108        let db_key = format!("databases.{}", db_name);
109        let default_pool_size = rocket
110            .figment()
111            .extract_inner::<u32>(rocket::Config::WORKERS)
112            .map(|workers| workers * 4)
113            .ok();
114
115        let figment = Figment::from(rocket.figment())
116            .focus(&db_key)
117            .join(Serialized::default("timeout", 5));
118
119        match default_pool_size {
120            Some(pool_size) => figment.join(Serialized::default("pool_size", pool_size)),
121            None => figment,
122        }
123    }
124}