Skip to content

Commit 96577d4

Browse files
authored
Merge pull request suharev7#50 from jspeis/master
Adding client side timeout options for queries
2 parents 324f9cd + 8333ea9 commit 96577d4

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ macro_rules! row {
202202
};
203203
}
204204

205+
#[macro_export]
205206
macro_rules! try_opt {
206207
($expr:expr) => {
207208
match $expr {

src/pool/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,4 +467,19 @@ mod test {
467467

468468
run(done).unwrap();
469469
}
470+
471+
#[test]
472+
fn test_query_timeout() {
473+
let test_db_url = format!("{}{}", DATABASE_URL.as_str(), "&query_timeout=5ms");
474+
let pool = Pool::new(test_db_url.to_string());
475+
476+
let done = pool.get_handle()
477+
.and_then(|c| c.query("SELECT sleep(10)").fetch_all());
478+
479+
480+
run(done).unwrap_err();
481+
482+
let info = pool.info();
483+
assert_eq!(info.ongoing, 0);
484+
}
470485
}

src/types/options.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ pub struct Options {
167167

168168
/// Timeout for connection (defaults to `500 ms`)
169169
pub(crate) connection_timeout: Duration,
170+
171+
/// Timeout for queries (defaults to `180,000 ms`)
172+
pub(crate) query_timeout: Duration,
173+
174+
/// Timeout for each block in a query (defaults to `180,000 ms`)
175+
pub(crate) query_block_timeout: Duration,
170176
}
171177

172178
impl Default for Options {
@@ -186,6 +192,8 @@ impl Default for Options {
186192
retry_timeout: Duration::from_secs(5),
187193
ping_timeout: Duration::from_millis(500),
188194
connection_timeout: Duration::from_millis(500),
195+
query_timeout: Duration::from_millis(180_000),
196+
query_block_timeout: Duration::from_millis(180_000),
189197
}
190198
}
191199
}
@@ -289,6 +297,16 @@ impl Options {
289297
/// Timeout for connection (defaults to `500 ms`).
290298
=> connection_timeout: Duration
291299
}
300+
301+
property! {
302+
/// Timeout for query (defaults to `180,000 ms`).
303+
=> query_timeout: Duration
304+
}
305+
306+
property! {
307+
/// Timeout for each block in a query (defaults to `180,000 ms`).
308+
=> query_block_timeout: Duration
309+
}
292310
}
293311

294312
impl FromStr for Options {
@@ -357,7 +375,13 @@ where
357375
"ping_timeout" => options.ping_timeout = parse_param(key, value, parse_duration)?,
358376
"connection_timeout" => {
359377
options.connection_timeout = parse_param(key, value, parse_duration)?
360-
}
378+
},
379+
"query_timeout" => {
380+
options.query_timeout = parse_param(key, value, parse_duration)?
381+
},
382+
"query_block_timeout" => {
383+
options.query_block_timeout = parse_param(key, value, parse_duration)?
384+
},
361385
"compression" => options.compression = parse_param(key, value, parse_compression)?,
362386
_ => return Err(UrlError::UnknownParameter { param: key.into() }),
363387
};

src/types/query_result/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
Rows,
1111
},
1212
ClientHandle,
13+
try_opt,
1314
};
1415

1516
use self::{either::Either, fold_block::FoldBlock};
@@ -18,6 +19,16 @@ mod either;
1819
mod fold_block;
1920
mod stream_blocks;
2021

22+
23+
macro_rules! try_opt_stream {
24+
($expr:expr) => {
25+
match $expr {
26+
Ok(val) => val,
27+
Err(err) => return Box::new(stream::once(Err(err))),
28+
}
29+
};
30+
}
31+
2132
/// Result of a query or statement execution.
2233
pub struct QueryResult {
2334
pub(crate) client: ClientHandle,
@@ -65,14 +76,18 @@ impl QueryResult {
6576

6677
/// Fetch data from table. It returns a block that contains all rows.
6778
pub fn fetch_all(self) -> BoxFuture<(ClientHandle, Block)> {
79+
let timeout = try_opt!(self.client.context.options.get()).query_timeout;
80+
6881
wrap_future(
6982
self.fold_blocks(Vec::new(), |mut blocks, block| {
7083
if !block.is_empty() {
7184
blocks.push(block);
7285
}
7386
Ok(blocks)
7487
})
75-
.map(|(h, blocks)| (h, Block::concat(blocks.as_slice()))),
88+
.timeout(timeout)
89+
.map_err(Error::from)
90+
.map(|(h, blocks)| (h, Block::concat(blocks.as_slice())))
7691
)
7792
}
7893

@@ -163,6 +178,7 @@ impl QueryResult {
163178
/// ```
164179
pub fn stream_blocks(self) -> BoxStream<Block> {
165180
let query = self.query;
181+
let timeout = try_opt_stream!(self.client.context.options.get()).query_block_timeout;
166182

167183
self.client.wrap_stream(move |mut c| {
168184
info!("[send query] {}", query.get_sql());
@@ -180,6 +196,8 @@ impl QueryResult {
180196
context,
181197
pool,
182198
)
199+
.timeout(timeout)
200+
.map_err(Error::from)
183201
})
184202
}
185203

0 commit comments

Comments
 (0)