Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timeout support in queries #47

Merged
merged 6 commits into from
Dec 11, 2024
Merged

Add timeout support in queries #47

merged 6 commits into from
Dec 11, 2024

Conversation

ghivert
Copy link
Contributor

@ghivert ghivert commented Nov 25, 2024

Hi!

Goal

This PR aims to add timeout support to pog.
This PR serves the purpose to start the conversation to find the best API & the best implementation, and is probably subject to future iterations, so take it as is.

To implement timeout, the idea consists to completely overrides the default parameter of pgo, to rely only on pog.
Timeout configuration is now stored in two places: the default configuration, and per-query. This makes sense if you consider some individual queries have to run longer than others, maybe because they won't be exposed on the WWW, but used asynchronously in actors. In the same time, having the default configuration allows for a centralized way to make sure every queries have a correct default timeout value.

By default, timeout has a value of 5000 ms, the current value provided by pgo.

Implementation details

To pass options to pgo:query, we need to target the 3rd argument of query/3. As of now, it's only used to pass the pool atom. The PR modifies run_query in Gleam to support a 4th argument, here the timeout.
I hesitated to directly pass the pool_options tuple needed in pgo, or simply the timeout like it is now. Passing the whole options record would allow for easier increments in the future, to add new features. In the same time, simply passing Option(Int) makes a really simple API, and it could be iterated later.

I'd be happy to discuss about it, and I'd be happy to change the way it works now to implement better options handling. They should probably be more thought out to find the correct format?

Currently, pgo does not properly handle timeout, and simply returns the {error, closed} tuple when the query times out. The issue should be tracked in erleans/pgo#96.

EUnit defaults needed to be updated to avoid timeouts after 5s. By default, EUnit timeout after 5s. To properly test timeouts, I need to increase the timeouts to test them. The time could probably be modified though.

Issues

Copy link
Owner

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thank you!

Could you change the timeout tests to timeout after a handful of milliseconds please? Using multi-second long tests does not verify any additional over faster ones, but they are a much worse developer experience.

@ghivert ghivert force-pushed the main branch 2 times, most recently from a847668 to 14654e1 Compare November 25, 2024 22:17
@ghivert
Copy link
Contributor Author

ghivert commented Nov 25, 2024

This looks great! Thank you!

Could you change the timeout tests to timeout after a handful of milliseconds please? Using multi-second long tests does not verify any additional over faster ones, but they are a much worse developer experience.

It's done!

Copy link
Owner

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Few small notes inline

let db = start_default()

pog.query("select sub.ret from (select pg_sleep(0.1), 'OK' as ret) as sub")
|> pog.timeout(1000)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smaller please! Tens of ms

src/pog.gleam Show resolved Hide resolved
src/pog.gleam Outdated
@@ -54,6 +54,9 @@ pub type Config {
/// (default: False) By default, pgo will return a n-tuple, in the order of the query.
/// By setting `rows_as_map` to `True`, the result will be `Dict`.
rows_as_map: Bool,
/// (default: 5000): Default time to wait before the query is considered timeout.
/// Timeout can be edited per query.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the unit for this?

}

/// Push a new query parameter value for the query.
pub fn parameter(query: Query(t1), parameter: Value) -> Query(t1) {
Query(..query, parameters: [parameter, ..query.parameters])
}

pub fn timeout(query: Query(t1), timeout: Int) -> Query(t1) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document this please 🙏

@ghivert
Copy link
Contributor Author

ghivert commented Dec 5, 2024

Done

@ghivert ghivert requested a review from lpil December 5, 2024 16:30
Copy link
Owner

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!!

@lpil lpil merged commit 2ef020f into lpil:main Dec 11, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for query timeout
2 participants