Skip to content

Commit 4a87b48

Browse files
authored
Add more pool settings (#416)
* Add some pool settings * fmt
1 parent cb5ff40 commit 4a87b48

File tree

5 files changed

+141
-18
lines changed

5 files changed

+141
-18
lines changed

CONFIG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ default: 30000 # milliseconds
4949

5050
How long an idle connection with a server is left open (ms).
5151

52+
### server_lifetime
53+
```
54+
path: general.server_lifetime
55+
default: 86400000 # 24 hours
56+
```
57+
58+
Max connection lifetime before it's closed, even if actively used.
59+
5260
### idle_client_in_transaction_timeout
5361
```
5462
path: general.idle_client_in_transaction_timeout

pgcat.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ connect_timeout = 5000 # milliseconds
2323
# How long an idle connection with a server is left open (ms).
2424
idle_timeout = 30000 # milliseconds
2525

26+
# Max connection lifetime before it's closed, even if actively used.
27+
server_lifetime = 86400000 # 24 hours
28+
2629
# How long a client is allowed to be idle while in a transaction (ms).
2730
idle_client_in_transaction_timeout = 0 # milliseconds
2831

@@ -206,6 +209,8 @@ sharding_function = "pg_bigint_hash"
206209
username = "simple_user"
207210
password = "simple_user"
208211
pool_size = 5
212+
min_pool_size = 3
213+
server_lifetime = 60000
209214
statement_timeout = 0
210215

211216
[pools.simple_db.shards.0]

src/auth_passthrough.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ impl AuthPassthrough {
7777
pool_size: 1,
7878
statement_timeout: 0,
7979
pool_mode: None,
80+
server_lifetime: None,
81+
min_pool_size: None,
8082
};
8183

8284
let user = &address.username;

src/config.rs

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ pub struct User {
181181
pub server_username: Option<String>,
182182
pub server_password: Option<String>,
183183
pub pool_size: u32,
184+
pub min_pool_size: Option<u32>,
184185
pub pool_mode: Option<PoolMode>,
186+
pub server_lifetime: Option<u64>,
185187
#[serde(default)] // 0
186188
pub statement_timeout: u64,
187189
}
@@ -194,12 +196,34 @@ impl Default for User {
194196
server_username: None,
195197
server_password: None,
196198
pool_size: 15,
199+
min_pool_size: None,
197200
statement_timeout: 0,
198201
pool_mode: None,
202+
server_lifetime: None,
199203
}
200204
}
201205
}
202206

207+
impl User {
208+
fn validate(&self) -> Result<(), Error> {
209+
match self.min_pool_size {
210+
Some(min_pool_size) => {
211+
if min_pool_size > self.pool_size {
212+
error!(
213+
"min_pool_size of {} cannot be larger than pool_size of {}",
214+
min_pool_size, self.pool_size
215+
);
216+
return Err(Error::BadConfig);
217+
}
218+
}
219+
220+
None => (),
221+
};
222+
223+
Ok(())
224+
}
225+
}
226+
203227
/// General configuration.
204228
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
205229
pub struct General {
@@ -246,6 +270,9 @@ pub struct General {
246270
#[serde(default = "General::default_idle_client_in_transaction_timeout")]
247271
pub idle_client_in_transaction_timeout: u64,
248272

273+
#[serde(default = "General::default_server_lifetime")]
274+
pub server_lifetime: u64,
275+
249276
#[serde(default = "General::default_worker_threads")]
250277
pub worker_threads: usize,
251278

@@ -271,6 +298,10 @@ impl General {
271298
5432
272299
}
273300

301+
pub fn default_server_lifetime() -> u64 {
302+
1000 * 60 * 60 * 24 // 24 hours
303+
}
304+
274305
pub fn default_connect_timeout() -> u64 {
275306
1000
276307
}
@@ -347,6 +378,7 @@ impl Default for General {
347378
auth_query: None,
348379
auth_query_user: None,
349380
auth_query_password: None,
381+
server_lifetime: 1000 * 3600 * 24, // 24 hours,
350382
}
351383
}
352384
}
@@ -411,6 +443,8 @@ pub struct Pool {
411443

412444
pub idle_timeout: Option<u64>,
413445

446+
pub server_lifetime: Option<u64>,
447+
414448
pub sharding_function: ShardingFunction,
415449

416450
#[serde(default = "Pool::default_automatic_sharding_key")]
@@ -515,6 +549,10 @@ impl Pool {
515549
None => None,
516550
};
517551

552+
for (_, user) in &self.users {
553+
user.validate()?;
554+
}
555+
518556
Ok(())
519557
}
520558
}
@@ -539,6 +577,7 @@ impl Default for Pool {
539577
auth_query: None,
540578
auth_query_user: None,
541579
auth_query_password: None,
580+
server_lifetime: None,
542581
}
543582
}
544583
}
@@ -791,6 +830,10 @@ impl Config {
791830
);
792831
info!("Shutdown timeout: {}ms", self.general.shutdown_timeout);
793832
info!("Healthcheck delay: {}ms", self.general.healthcheck_delay);
833+
info!(
834+
"Default max server lifetime: {}ms",
835+
self.general.server_lifetime
836+
);
794837
match self.general.tls_certificate.clone() {
795838
Some(tls_certificate) => {
796839
info!("TLS certificate: {}", tls_certificate);
@@ -867,12 +910,26 @@ impl Config {
867910
pool_name,
868911
pool_config.users.len()
869912
);
913+
info!(
914+
"[pool: {}] Max server lifetime: {}",
915+
pool_name,
916+
match pool_config.server_lifetime {
917+
Some(server_lifetime) => format!("{}ms", server_lifetime),
918+
None => "default".to_string(),
919+
}
920+
);
870921

871922
for user in &pool_config.users {
872923
info!(
873924
"[pool: {}][user: {}] Pool size: {}",
874925
pool_name, user.1.username, user.1.pool_size,
875926
);
927+
info!(
928+
"[pool: {}][user: {}] Minimum pool size: {}",
929+
pool_name,
930+
user.1.username,
931+
user.1.min_pool_size.unwrap_or(0)
932+
);
876933
info!(
877934
"[pool: {}][user: {}] Statement timeout: {}",
878935
pool_name, user.1.username, user.1.statement_timeout
@@ -886,6 +943,15 @@ impl Config {
886943
None => pool_config.pool_mode.to_string(),
887944
}
888945
);
946+
info!(
947+
"[pool: {}][user: {}] Max server lifetime: {}",
948+
pool_name,
949+
user.1.username,
950+
match user.1.server_lifetime {
951+
Some(server_lifetime) => format!("{}ms", server_lifetime),
952+
None => "default".to_string(),
953+
}
954+
);
889955
}
890956
}
891957
}
@@ -896,15 +962,28 @@ impl Config {
896962
&& (self.general.auth_query_user.is_none()
897963
|| self.general.auth_query_password.is_none())
898964
{
899-
error!("If auth_query is specified, you need to provide a value for `auth_query_user`, `auth_query_password`");
965+
error!(
966+
"If auth_query is specified, \
967+
you need to provide a value \
968+
for `auth_query_user`, \
969+
`auth_query_password`"
970+
);
971+
900972
return Err(Error::BadConfig);
901973
}
902974

903975
for (name, pool) in self.pools.iter() {
904976
if pool.auth_query.is_some()
905977
&& (pool.auth_query_user.is_none() || pool.auth_query_password.is_none())
906978
{
907-
error!("Error in pool {{ {} }}. If auth_query is specified, you need to provide a value for `auth_query_user`, `auth_query_password`", name);
979+
error!(
980+
"Error in pool {{ {} }}. \
981+
If auth_query is specified, you need \
982+
to provide a value for `auth_query_user`, \
983+
`auth_query_password`",
984+
name
985+
);
986+
908987
return Err(Error::BadConfig);
909988
}
910989

@@ -914,7 +993,13 @@ impl Config {
914993
|| pool.auth_query_user.is_none())
915994
&& user_data.password.is_none()
916995
{
917-
error!("Error in pool {{ {} }}. You have to specify a user password for every pool if auth_query is not specified", name);
996+
error!(
997+
"Error in pool {{ {} }}. \
998+
You have to specify a user password \
999+
for every pool if auth_query is not specified",
1000+
name
1001+
);
1002+
9181003
return Err(Error::BadConfig);
9191004
}
9201005
}

src/pool.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -311,21 +311,34 @@ impl ConnectionPool {
311311

312312
if let Some(apt) = &auth_passthrough {
313313
match apt.fetch_hash(&address).await {
314-
Ok(ok) => {
315-
if let Some(ref pool_auth_hash_value) = *(pool_auth_hash.read()) {
316-
if ok != *pool_auth_hash_value {
317-
warn!("Hash is not the same across shards of the same pool, client auth will \
318-
be done using last obtained hash. Server: {}:{}, Database: {}", server.host, server.port, shard.database);
319-
}
320-
}
321-
debug!("Hash obtained for {:?}", address);
322-
{
323-
let mut pool_auth_hash = pool_auth_hash.write();
324-
*pool_auth_hash = Some(ok.clone());
325-
}
326-
},
327-
Err(err) => warn!("Could not obtain password hashes using auth_query config, ignoring. Error: {:?}", err),
328-
}
314+
Ok(ok) => {
315+
if let Some(ref pool_auth_hash_value) = *(pool_auth_hash.read())
316+
{
317+
if ok != *pool_auth_hash_value {
318+
warn!(
319+
"Hash is not the same across shards \
320+
of the same pool, client auth will \
321+
be done using last obtained hash. \
322+
Server: {}:{}, Database: {}",
323+
server.host, server.port, shard.database,
324+
);
325+
}
326+
}
327+
328+
debug!("Hash obtained for {:?}", address);
329+
330+
{
331+
let mut pool_auth_hash = pool_auth_hash.write();
332+
*pool_auth_hash = Some(ok.clone());
333+
}
334+
}
335+
Err(err) => warn!(
336+
"Could not obtain password hashes \
337+
using auth_query config, ignoring. \
338+
Error: {:?}",
339+
err,
340+
),
341+
}
329342
}
330343

331344
let manager = ServerPool::new(
@@ -347,10 +360,20 @@ impl ConnectionPool {
347360
None => config.general.idle_timeout,
348361
};
349362

363+
let server_lifetime = match user.server_lifetime {
364+
Some(server_lifetime) => server_lifetime,
365+
None => match pool_config.server_lifetime {
366+
Some(server_lifetime) => server_lifetime,
367+
None => config.general.server_lifetime,
368+
},
369+
};
370+
350371
let pool = Pool::builder()
351372
.max_size(user.pool_size)
373+
.min_idle(user.min_pool_size)
352374
.connection_timeout(std::time::Duration::from_millis(connect_timeout))
353375
.idle_timeout(Some(std::time::Duration::from_millis(idle_timeout)))
376+
.max_lifetime(Some(std::time::Duration::from_millis(server_lifetime)))
354377
.test_on_check_out(false)
355378
.build(manager)
356379
.await

0 commit comments

Comments
 (0)