-
Notifications
You must be signed in to change notification settings - Fork 35
Add configurable checkout timeout for transactions #83
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,8 @@ | |
|
|
||
| // TODO: add time things with zone once pgo supports them | ||
|
|
||
| const default_checkout_timeout = 5000 | ||
|
|
||
| import exception | ||
| import gleam/dynamic.{type Dynamic} | ||
| import gleam/dynamic/decode.{type Decoder} | ||
|
|
@@ -25,7 +27,7 @@ import gleam/uri.{Uri} | |
| const default_port: Int = 5432 | ||
|
|
||
| pub opaque type Connection { | ||
| Pool(Name(Message)) | ||
| Pool(name: Name(Message), checkout_timeout: Int) | ||
| SingleConnection(SingleConnection) | ||
| } | ||
|
|
||
|
|
@@ -39,7 +41,20 @@ pub type Message | |
| /// connection will fail. | ||
| /// | ||
| pub fn named_connection(name: Name(Message)) -> Connection { | ||
| Pool(name) | ||
| Pool(name:, checkout_timeout: default_checkout_timeout) | ||
| } | ||
|
|
||
| /// Create a reference to a pool using the pool's name and an explicit | ||
| /// checkout timeout in milliseconds. | ||
| /// | ||
| /// Use this when the pool was started with a non-default `checkout_timeout` | ||
| /// and you need transactions on this connection to use the same timeout. | ||
| /// | ||
| pub fn named_connection_with_timeout( | ||
| name: Name(Message), | ||
| checkout_timeout timeout: Int, | ||
| ) -> Connection { | ||
| Pool(name:, checkout_timeout: timeout) | ||
| } | ||
|
|
||
| /// The configuration for a pool of connections. | ||
|
|
@@ -75,6 +90,11 @@ pub type Config { | |
| /// (default: 1000): The database is pinged every idle_interval when the | ||
| /// connection is idle. | ||
| idle_interval: Int, | ||
| /// (default: 5000): Timeout in milliseconds for checking out a connection | ||
| /// from the pool. Used by `transaction` when acquiring a dedicated | ||
| /// connection. If the checkout takes longer than this, the transaction | ||
| /// fails with `QueryTimeout`. | ||
| checkout_timeout: Int, | ||
| /// trace (default: False): pgo is instrumented with [OpenCensus][1] and | ||
| /// when this option is true a span will be created (if sampled). | ||
| /// | ||
|
|
@@ -189,6 +209,14 @@ pub fn idle_interval(config: Config, idle_interval: Int) -> Config { | |
| Config(..config, idle_interval:) | ||
| } | ||
|
|
||
| /// Timeout in milliseconds for checking out a connection from the pool. | ||
| /// Used by `transaction` when acquiring a dedicated connection. | ||
| /// | ||
| /// default: 5000 | ||
| pub fn checkout_timeout(config: Config, checkout_timeout: Int) -> Config { | ||
| Config(..config, checkout_timeout:) | ||
| } | ||
|
|
||
| /// Trace pgo is instrumented with [OpenTelemetry][1] and | ||
| /// when this option is true a span will be created (if sampled). | ||
| /// | ||
|
|
@@ -235,6 +263,7 @@ pub fn default_config(pool_name pool_name: Name(Message)) -> Config { | |
| queue_target: 50, | ||
| queue_interval: 1000, | ||
| idle_interval: 1000, | ||
| checkout_timeout: default_checkout_timeout, | ||
| trace: False, | ||
| ip_version: Ipv4, | ||
| rows_as_map: False, | ||
|
|
@@ -335,7 +364,11 @@ fn extract_ssl_mode(query: option.Option(String)) -> Result(Ssl, Nil) { | |
| /// | ||
| pub fn start(config: Config) -> actor.StartResult(Connection) { | ||
| case start_tree(config) { | ||
| Ok(pid) -> Ok(actor.Started(pid, Pool(config.pool_name))) | ||
| Ok(pid) -> | ||
| Ok(actor.Started( | ||
| pid, | ||
| Pool(name: config.pool_name, checkout_timeout: config.checkout_timeout), | ||
| )) | ||
| Error(reason) -> Error(actor.InitExited(process.Abnormal(reason))) | ||
| } | ||
| } | ||
|
|
@@ -431,10 +464,11 @@ pub fn transaction( | |
| SingleConnection(conn) -> { | ||
| transaction_layer(conn, callback) | ||
| } | ||
| Pool(name) -> { | ||
| Pool(name:, checkout_timeout:) -> { | ||
| // Check out a single connection from the pool | ||
| use #(ref, conn) <- result.try( | ||
| checkout(name) |> result.map_error(TransactionQueryError), | ||
| checkout(name, checkout_timeout) | ||
| |> result.map_error(TransactionQueryError), | ||
| ) | ||
|
Comment on lines
+467
to
472
|
||
|
|
||
| // Make a best attempt to check back in the connection, even if this | ||
|
|
@@ -481,6 +515,7 @@ fn transaction_layer( | |
| @external(erlang, "pog_ffi", "checkout") | ||
| fn checkout( | ||
| pool: Name(Message), | ||
| timeout: Int, | ||
| ) -> Result(#(Reference, SingleConnection), QueryError) | ||
|
|
||
| @external(erlang, "pgo", "checkin") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default checkout timeout value
5000is duplicated (e.g.named_connectionanddefault_config). To avoid drift if this default changes, consider introducing a single module-level constant (e.g.default_checkout_timeout) and referencing it in both places.