mysql/conn/opts/pool_opts.rs
1// Copyright (c) 2023 rust-mysql-simple contributors
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9macro_rules! const_assert {
10 ($name:ident, $($xs:expr),+ $(,)*) => {
11 #[allow(unknown_lints, clippy::eq_op)]
12 const $name: [(); 0 - !($($xs)&&+) as usize] = [];
13 };
14}
15
16/// Connection pool options.
17///
18/// ```
19/// # use mysql::{PoolOpts, PoolConstraints};
20/// # use std::time::Duration;
21/// let pool_opts = PoolOpts::default()
22/// .with_constraints(PoolConstraints::new(15, 30).unwrap())
23/// .with_reset_connection(false);
24/// ```
25#[derive(Debug, Clone, Eq, PartialEq, Hash)]
26pub struct PoolOpts {
27 constraints: PoolConstraints,
28 reset_connection: bool,
29 check_health: bool,
30}
31
32impl PoolOpts {
33 /// Calls `Self::default`.
34 pub fn new() -> Self {
35 Self::default()
36 }
37
38 /// Creates the default [`PoolOpts`] with the given constraints.
39 pub fn with_constraints(mut self, constraints: PoolConstraints) -> Self {
40 self.constraints = constraints;
41 self
42 }
43
44 /// Returns pool constraints.
45 pub fn constraints(&self) -> PoolConstraints {
46 self.constraints
47 }
48
49 /// Sets whether to reset the connection upon returning it to a pool (defaults to `true`).
50 ///
51 /// Default behavior increases reliability but comes with cons:
52 ///
53 /// * reset procedure removes all prepared statements, i.e. kills prepared statements cache
54 /// * connection reset is quite fast but requires additional client-server roundtrip
55 /// (might require re-authentication for older servers)
56 ///
57 /// The purpose of the reset procedure is to:
58 ///
59 /// * rollback any opened transactions
60 /// * reset transaction isolation level
61 /// * reset session variables
62 /// * delete user variables
63 /// * remove temporary tables
64 /// * remove all PREPARE statement (this action kills prepared statements cache)
65 ///
66 /// So to increase overall performance you can safely opt-out of the default behavior
67 /// if you are not willing to change the session state in an unpleasant way.
68 ///
69 /// It is also possible to selectively opt-in/out using [`crate::PooledConn::reset_connection`].
70 ///
71 /// # Connection URL
72 ///
73 /// You can use `reset_connection` URL parameter to set this value. E.g.
74 ///
75 /// ```
76 /// # use mysql::*;
77 /// # use std::time::Duration;
78 /// # fn main() -> Result<()> {
79 /// let opts = Opts::from_url("mysql://localhost/db?reset_connection=false")?;
80 /// assert_eq!(opts.get_pool_opts().reset_connection(), false);
81 /// # Ok(()) }
82 /// ```
83 pub fn with_reset_connection(mut self, reset_connection: bool) -> Self {
84 self.reset_connection = reset_connection;
85 self
86 }
87
88 /// Returns the `reset_connection` value (see [`PoolOpts::with_reset_connection`]).
89 pub fn reset_connection(&self) -> bool {
90 self.reset_connection
91 }
92
93 /// Sets whether to check connection health upon retrieving it from a pool (defaults to `true`).
94 ///
95 /// If `true`, then `Conn::ping` will be invoked on a non-fresh pooled connection.
96 ///
97 /// # Connection URL
98 ///
99 /// Use `check_health` URL parameter to set this value. E.g.
100 ///
101 /// ```
102 /// # use mysql::*;
103 /// # use std::time::Duration;
104 /// # fn main() -> Result<()> {
105 /// let opts = Opts::from_url("mysql://localhost/db?check_health=false")?;
106 /// assert_eq!(opts.get_pool_opts().check_health(), false);
107 /// # Ok(()) }
108 /// ```
109 pub fn with_check_health(mut self, check_health: bool) -> Self {
110 self.check_health = check_health;
111 self
112 }
113
114 pub fn check_health(&self) -> bool {
115 self.check_health
116 }
117}
118
119impl Default for PoolOpts {
120 fn default() -> Self {
121 Self {
122 constraints: PoolConstraints::DEFAULT,
123 reset_connection: true,
124 check_health: true,
125 }
126 }
127}
128
129/// Connection pool constraints.
130///
131/// This type stores `min` and `max` constraints for [`crate::Pool`] and ensures that `min <= max`.
132#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
133pub struct PoolConstraints {
134 min: usize,
135 max: usize,
136}
137
138const_assert!(
139 _DEFAULT_POOL_CONSTRAINTS_ARE_CORRECT,
140 PoolConstraints::DEFAULT.min <= PoolConstraints::DEFAULT.max,
141);
142
143pub struct Assert<const L: usize, const R: usize>;
144impl<const L: usize, const R: usize> Assert<L, R> {
145 pub const LEQ: usize = R - L;
146}
147
148#[allow(path_statements)]
149pub const fn gte<const M: usize, const N: usize>() {
150 #[allow(clippy::no_effect)]
151 Assert::<M, N>::LEQ;
152}
153
154impl PoolConstraints {
155 /// Default pool constraints.
156 pub const DEFAULT: PoolConstraints = PoolConstraints { min: 10, max: 100 };
157
158 /// Creates new [`PoolConstraints`] if constraints are valid (`min <= max`).
159 ///
160 /// # Connection URL
161 ///
162 /// You can use `pool_min` and `pool_max` URL parameters to define pool constraints.
163 ///
164 /// ```
165 /// # use mysql::*;
166 /// # fn main() -> Result<()> {
167 /// let opts = Opts::from_url("mysql://localhost/db?pool_min=0&pool_max=151")?;
168 /// assert_eq!(opts.get_pool_opts().constraints(), PoolConstraints::new(0, 151).unwrap());
169 /// # Ok(()) }
170 /// ```
171 pub fn new(min: usize, max: usize) -> Option<PoolConstraints> {
172 if min <= max {
173 Some(PoolConstraints { min, max })
174 } else {
175 None
176 }
177 }
178
179 pub const fn new_const<const MIN: usize, const MAX: usize>() -> PoolConstraints {
180 gte::<MIN, MAX>();
181 PoolConstraints { min: MIN, max: MAX }
182 }
183
184 /// Lower bound of this pool constraints.
185 pub const fn min(&self) -> usize {
186 self.min
187 }
188
189 /// Upper bound of this pool constraints.
190 pub const fn max(&self) -> usize {
191 self.max
192 }
193}
194
195impl Default for PoolConstraints {
196 fn default() -> Self {
197 PoolConstraints::DEFAULT
198 }
199}
200
201impl From<PoolConstraints> for (usize, usize) {
202 /// Transforms constraints to a pair of `(min, max)`.
203 fn from(PoolConstraints { min, max }: PoolConstraints) -> Self {
204 (min, max)
205 }
206}