Skip to content

pog.transaction checkout uses hardcoded 5s timeout, ignoring pool config #82

@mgruen

Description

@mgruen

Problem

pog.transaction calls pgo:checkout(Name) with no timeout option, which defaults to pgo_pool's hardcoded ?TIMEOUT of 5000ms:

% pog_ffi.erl line 113
checkout(Name) when is_atom(Name) ->
    case pgo:checkout(Name) of  %% <-- no timeout passed

Meanwhile, pog.query passes the timeout correctly:

% pog_ffi.erl line 90-94
Options = #{
    pool => Name,
    pool_options => [{timeout, Timeout}]  %% <-- timeout passed
},
pgo:query(Sql, Arguments, Options)

This means queue_target and queue_interval pool config have no effect on transaction checkout. Any serverless database (Neon, Supabase) with >5s cold starts, or cross-region connections with high latency, will hit TransactionQueryError(QueryTimeout) on transactions while regular queries work fine.

Reproduction

// This works — timeout is passed through to pgo:query
pog.query("SELECT 1")
|> pog.timeout(30_000)
|> pog.execute(db)

// This fails with QueryTimeout after exactly 5s — timeout is not configurable
pog.transaction(db, fn(tx) {
  // ... any queries ...
})

Suggested fix

Pass a configurable timeout to pgo:checkout/2 in the transaction path:

checkout(Name, Timeout) when is_atom(Name) ->
    case pgo:checkout(Name, [{timeout, Timeout}]) of
        {ok, Ref, Conn} -> {ok, {Ref, Conn}};
        {error, Error} -> {error, convert_error(Error)}
    end.

And expose it in the Gleam API, perhaps as a second argument to pog.transaction or via the pool config.

Context

Discovered while deploying a Gleam/wisp app on connecting to a distant PostgreSQL. Regular queries worked, but transactions with multiple round-trips exceeded the 5s hardcoded limit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions