Skip to content

Commit faedb49

Browse files
committed
Merge branch 'master' into tdinh/hostaddr
2 parents b46ea89 + 14e11bd commit faedb49

File tree

9 files changed

+147
-17
lines changed

9 files changed

+147
-17
lines changed

postgres/src/config.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ use tokio_postgres::{Error, Socket};
4848
/// This option is ignored when connecting with Unix sockets. Defaults to on.
4949
/// * `keepalives_idle` - The number of seconds of inactivity after which a keepalive message is sent to the server.
5050
/// This option is ignored when connecting with Unix sockets. Defaults to 2 hours.
51+
/// * `keepalives_interval` - The time interval between TCP keepalive probes.
52+
/// This option is ignored when connecting with Unix sockets.
53+
/// * `keepalives_retries` - The maximum number of TCP keepalive probes that will be sent before dropping a connection.
54+
/// This option is ignored when connecting with Unix sockets.
5155
/// * `target_session_attrs` - Specifies requirements of the session. If set to `read-write`, the client will check that
5256
/// the `transaction_read_write` session parameter is set to `on`. This can be used to connect to the primary server
5357
/// in a database cluster as opposed to the secondary read-only mirrors. Defaults to `all`.
@@ -279,6 +283,33 @@ impl Config {
279283
self.config.get_keepalives_idle()
280284
}
281285

286+
/// Sets the time interval between TCP keepalive probes.
287+
/// On Windows, this sets the value of the tcp_keepalive struct’s keepaliveinterval field.
288+
///
289+
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
290+
pub fn keepalives_interval(&mut self, keepalives_interval: Duration) -> &mut Config {
291+
self.config.keepalives_interval(keepalives_interval);
292+
self
293+
}
294+
295+
/// Gets the time interval between TCP keepalive probes.
296+
pub fn get_keepalives_interval(&self) -> Option<Duration> {
297+
self.config.get_keepalives_interval()
298+
}
299+
300+
/// Sets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
301+
///
302+
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
303+
pub fn keepalives_retries(&mut self, keepalives_retries: u32) -> &mut Config {
304+
self.config.keepalives_retries(keepalives_retries);
305+
self
306+
}
307+
308+
/// Gets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
309+
pub fn get_keepalives_retries(&self) -> Option<u32> {
310+
self.config.get_keepalives_retries()
311+
}
312+
282313
/// Sets the requirements of the session.
283314
///
284315
/// This can be used to connect to the primary server in a clustered database rather than one of the read-only

tokio-postgres/src/cancel_query.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ where
3838
&config.host,
3939
config.port,
4040
config.connect_timeout,
41-
config.keepalives,
42-
config.keepalives_idle,
41+
config.keepalive.as_ref(),
4342
)
4443
.await?;
4544

tokio-postgres/src/client.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use crate::config::Host;
44
use crate::config::SslMode;
55
use crate::connection::{Request, RequestMessages};
66
use crate::copy_out::CopyOutStream;
7+
#[cfg(feature = "runtime")]
8+
use crate::keepalive::KeepaliveConfig;
79
use crate::query::RowStream;
810
use crate::simple_query::SimpleQueryStream;
911
#[cfg(feature = "runtime")]
@@ -154,8 +156,7 @@ pub(crate) struct SocketConfig {
154156
pub host: Host,
155157
pub port: u16,
156158
pub connect_timeout: Option<Duration>,
157-
pub keepalives: bool,
158-
pub keepalives_idle: Duration,
159+
pub keepalive: Option<KeepaliveConfig>,
159160
}
160161

161162
/// An asynchronous PostgreSQL client.

tokio-postgres/src/config.rs

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#[cfg(feature = "runtime")]
44
use crate::connect::connect;
55
use crate::connect_raw::connect_raw;
6+
use crate::keepalive::KeepaliveConfig;
67
#[cfg(feature = "runtime")]
78
use crate::tls::MakeTlsConnect;
89
use crate::tls::TlsConnect;
@@ -111,6 +112,10 @@ pub enum Host {
111112
/// This option is ignored when connecting with Unix sockets. Defaults to on.
112113
/// * `keepalives_idle` - The number of seconds of inactivity after which a keepalive message is sent to the server.
113114
/// This option is ignored when connecting with Unix sockets. Defaults to 2 hours.
115+
/// * `keepalives_interval` - The time interval between TCP keepalive probes.
116+
/// This option is ignored when connecting with Unix sockets.
117+
/// * `keepalives_retries` - The maximum number of TCP keepalive probes that will be sent before dropping a connection.
118+
/// This option is ignored when connecting with Unix sockets.
114119
/// * `target_session_attrs` - Specifies requirements of the session. If set to `read-write`, the client will check that
115120
/// the `transaction_read_write` session parameter is set to `on`. This can be used to connect to the primary server
116121
/// in a database cluster as opposed to the secondary read-only mirrors. Defaults to `all`.
@@ -173,7 +178,7 @@ pub struct Config {
173178
pub(crate) port: Vec<u16>,
174179
pub(crate) connect_timeout: Option<Duration>,
175180
pub(crate) keepalives: bool,
176-
pub(crate) keepalives_idle: Duration,
181+
pub(crate) keepalive_config: KeepaliveConfig,
177182
pub(crate) target_session_attrs: TargetSessionAttrs,
178183
pub(crate) channel_binding: ChannelBinding,
179184
}
@@ -187,6 +192,11 @@ impl Default for Config {
187192
impl Config {
188193
/// Creates a new configuration.
189194
pub fn new() -> Config {
195+
let keepalive_config = KeepaliveConfig {
196+
idle: Duration::from_secs(2 * 60 * 60),
197+
interval: None,
198+
retries: None,
199+
};
190200
Config {
191201
user: None,
192202
password: None,
@@ -199,7 +209,7 @@ impl Config {
199209
port: vec![],
200210
connect_timeout: None,
201211
keepalives: true,
202-
keepalives_idle: Duration::from_secs(2 * 60 * 60),
212+
keepalive_config,
203213
target_session_attrs: TargetSessionAttrs::Any,
204214
channel_binding: ChannelBinding::Prefer,
205215
}
@@ -379,14 +389,41 @@ impl Config {
379389
///
380390
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled. Defaults to 2 hours.
381391
pub fn keepalives_idle(&mut self, keepalives_idle: Duration) -> &mut Config {
382-
self.keepalives_idle = keepalives_idle;
392+
self.keepalive_config.idle = keepalives_idle;
383393
self
384394
}
385395

386396
/// Gets the configured amount of idle time before a keepalive packet will
387397
/// be sent on the connection.
388398
pub fn get_keepalives_idle(&self) -> Duration {
389-
self.keepalives_idle
399+
self.keepalive_config.idle
400+
}
401+
402+
/// Sets the time interval between TCP keepalive probes.
403+
/// On Windows, this sets the value of the tcp_keepalive struct’s keepaliveinterval field.
404+
///
405+
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
406+
pub fn keepalives_interval(&mut self, keepalives_interval: Duration) -> &mut Config {
407+
self.keepalive_config.interval = Some(keepalives_interval);
408+
self
409+
}
410+
411+
/// Gets the time interval between TCP keepalive probes.
412+
pub fn get_keepalives_interval(&self) -> Option<Duration> {
413+
self.keepalive_config.interval
414+
}
415+
416+
/// Sets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
417+
///
418+
/// This is ignored for Unix domain sockets, or if the `keepalives` option is disabled.
419+
pub fn keepalives_retries(&mut self, keepalives_retries: u32) -> &mut Config {
420+
self.keepalive_config.retries = Some(keepalives_retries);
421+
self
422+
}
423+
424+
/// Gets the maximum number of TCP keepalive probes that will be sent before dropping a connection.
425+
pub fn get_keepalives_retries(&self) -> Option<u32> {
426+
self.keepalive_config.retries
390427
}
391428

392429
/// Sets the requirements of the session.
@@ -488,6 +525,20 @@ impl Config {
488525
self.keepalives_idle(Duration::from_secs(keepalives_idle as u64));
489526
}
490527
}
528+
"keepalives_interval" => {
529+
let keepalives_interval = value.parse::<i64>().map_err(|_| {
530+
Error::config_parse(Box::new(InvalidValue("keepalives_interval")))
531+
})?;
532+
if keepalives_interval > 0 {
533+
self.keepalives_interval(Duration::from_secs(keepalives_interval as u64));
534+
}
535+
}
536+
"keepalives_retries" => {
537+
let keepalives_retries = value.parse::<u32>().map_err(|_| {
538+
Error::config_parse(Box::new(InvalidValue("keepalives_retries")))
539+
})?;
540+
self.keepalives_retries(keepalives_retries);
541+
}
491542
"target_session_attrs" => {
492543
let target_session_attrs = match value {
493544
"any" => TargetSessionAttrs::Any,
@@ -583,7 +634,9 @@ impl fmt::Debug for Config {
583634
.field("port", &self.port)
584635
.field("connect_timeout", &self.connect_timeout)
585636
.field("keepalives", &self.keepalives)
586-
.field("keepalives_idle", &self.keepalives_idle)
637+
.field("keepalives_idle", &self.keepalive_config.idle)
638+
.field("keepalives_interval", &self.keepalive_config.interval)
639+
.field("keepalives_retries", &self.keepalive_config.retries)
587640
.field("target_session_attrs", &self.target_session_attrs)
588641
.field("channel_binding", &self.channel_binding)
589642
.finish()

tokio-postgres/src/connect.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,11 @@ where
8484
host,
8585
port,
8686
config.connect_timeout,
87-
config.keepalives,
88-
config.keepalives_idle,
87+
if config.keepalives {
88+
Some(&config.keepalive_config)
89+
} else {
90+
None
91+
},
8992
)
9093
.await?;
9194
let (mut client, mut connection) = connect_raw(socket, tls, config).await?;
@@ -134,8 +137,11 @@ where
134137
host: host.clone(),
135138
port,
136139
connect_timeout: config.connect_timeout,
137-
keepalives: config.keepalives,
138-
keepalives_idle: config.keepalives_idle,
140+
keepalive: if config.keepalives {
141+
Some(config.keepalive_config.clone())
142+
} else {
143+
None
144+
},
139145
});
140146

141147
Ok((client, connection))

tokio-postgres/src/connect_socket.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::config::Host;
2+
use crate::keepalive::KeepaliveConfig;
23
use crate::{Error, Socket};
34
use socket2::{SockRef, TcpKeepalive};
45
use std::future::Future;
@@ -13,8 +14,7 @@ pub(crate) async fn connect_socket(
1314
host: &Host,
1415
port: u16,
1516
connect_timeout: Option<Duration>,
16-
keepalives: bool,
17-
keepalives_idle: Duration,
17+
keepalive_config: Option<&KeepaliveConfig>,
1818
) -> Result<Socket, Error> {
1919
match host {
2020
Host::Tcp(host) => {
@@ -35,9 +35,9 @@ pub(crate) async fn connect_socket(
3535
};
3636

3737
stream.set_nodelay(true).map_err(Error::connect)?;
38-
if keepalives {
38+
if let Some(keepalive_config) = keepalive_config {
3939
SockRef::from(&stream)
40-
.set_tcp_keepalive(&TcpKeepalive::new().with_time(keepalives_idle))
40+
.set_tcp_keepalive(&TcpKeepalive::from(keepalive_config))
4141
.map_err(Error::connect)?;
4242
}
4343

tokio-postgres/src/keepalive.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use socket2::TcpKeepalive;
2+
use std::time::Duration;
3+
4+
#[derive(Clone, PartialEq, Eq)]
5+
pub(crate) struct KeepaliveConfig {
6+
pub idle: Duration,
7+
pub interval: Option<Duration>,
8+
pub retries: Option<u32>,
9+
}
10+
11+
impl From<&KeepaliveConfig> for TcpKeepalive {
12+
fn from(keepalive_config: &KeepaliveConfig) -> Self {
13+
let mut tcp_keepalive = Self::new().with_time(keepalive_config.idle);
14+
15+
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
16+
if let Some(interval) = keepalive_config.interval {
17+
tcp_keepalive = tcp_keepalive.with_interval(interval);
18+
}
19+
20+
#[cfg(not(any(target_os = "redox", target_os = "solaris", target_os = "windows")))]
21+
if let Some(retries) = keepalive_config.retries {
22+
tcp_keepalive = tcp_keepalive.with_retries(retries);
23+
}
24+
25+
tcp_keepalive
26+
}
27+
}

tokio-postgres/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ mod copy_in;
163163
mod copy_out;
164164
pub mod error;
165165
mod generic_client;
166+
mod keepalive;
166167
mod maybe_tls_stream;
167168
mod portal;
168169
mod prepare;

tokio-postgres/tests/test/parse.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ fn settings() {
3636
);
3737
}
3838

39+
#[test]
40+
fn keepalive_settings() {
41+
check(
42+
"keepalives=1 keepalives_idle=15 keepalives_interval=5 keepalives_retries=9",
43+
Config::new()
44+
.keepalives(true)
45+
.keepalives_idle(Duration::from_secs(15))
46+
.keepalives_interval(Duration::from_secs(5))
47+
.keepalives_retries(9),
48+
);
49+
}
50+
3951
#[test]
4052
fn url() {
4153
check("postgresql://", &Config::new());

0 commit comments

Comments
 (0)