kura_pool behaviour (kura v2.0.6)

View Source

Pluggable connection-pool behaviour.

Each implementation manages a set of connections to a backend (Postgres, MySQL, SQLite, an HTTP client, etc.) and exposes a uniform checkout/checkin/give_away surface to kura_db and friends.

Different drivers want different pool shapes:

  • Network-protocol drivers like Postgres benefit from caller-side I/O on the socket, so the pool just hands out a connection record and stays out of the way (kura_pool_pgo, the canonical PG impl).
  • gen_server-style drivers like MySQL or HTTP clients want a worker process the caller calls into; a gen_server-call-style pool fits.

This behaviour is the contract; implementations pick the shape that matches their backend.

Token vs connection

checkout/2 returns both a conn() and a token(). The conn() is what callers actually use to run work (e.g. a pgo_pool:conn() record that pgo_handler:extended_query/4 accepts). The token() is the opaque value the caller hands back to checkin/2. Implementations are free to make them the same value if they like.

give_away/3 transfers ownership of an in-flight checkout to another process. The new owner becomes responsible for calling checkin/2. Used by sandbox test patterns: a setup process checks out a connection, transfers it to the test process for the duration of the test, and the teardown checks it back in.

Example

{ok, _Pid} = kura_pool_pgo:start_pool(my_pool, #{
    host => "localhost",
    database => "my_app",
    user => "postgres",
    password => "secret",
    pool_size => 10
}),

kura_pool:with_conn(kura_pool_pgo, my_pool, fun(Conn) ->
    pgo_handler:extended_query(Conn, ~"SELECT 1", [])
end).

Summary

Types

Implementation-specific options for a single checkout (e.g. #{timeout => 5000}).

Opaque per-impl connection handle the caller uses to run work.

Pool registration name. Implementation chooses the registry semantics.

Implementation-specific pool options. Pass through to start_pool/2.

Opaque per-impl token handed back to checkin/2.

Callbacks

Return a leased connection to the pool.

Lease a connection from the pool. Returns the conn and a checkin token.

Transfer ownership of a checked-out connection to another process.

Optional. Resize a running pool to Size connections.

Start a pool registered under Name.

Stop a previously-started pool.

Functions

Equivalent to with_conn(Mod, Name, Fun, #{}).

Lease a connection, run Fun(Conn), and check it back in.

Types

checkout_opts()

-type checkout_opts() :: map().

Implementation-specific options for a single checkout (e.g. #{timeout => 5000}).

conn()

-type conn() :: dynamic().

Opaque per-impl connection handle the caller uses to run work.

name()

-type name() :: atom().

Pool registration name. Implementation chooses the registry semantics.

opts()

-type opts() :: map().

Implementation-specific pool options. Pass through to start_pool/2.

token()

-type token() :: dynamic().

Opaque per-impl token handed back to checkin/2.

Callbacks

checkin/2

-callback checkin(name(), token()) -> ok.

Return a leased connection to the pool.

checkout/2

-callback checkout(name(), checkout_opts()) -> {ok, conn(), token()} | {error, term()}.

Lease a connection from the pool. Returns the conn and a checkin token.

give_away/3

-callback give_away(token(), pid(), term()) -> ok | {error, term()}.

Transfer ownership of a checked-out connection to another process.

The new owner becomes responsible for calling checkin/2. GiftData is delivered as a message to NewOwner if the underlying pool supports it; otherwise it is silently dropped.

resize/2

(optional)
-callback resize(name(), pos_integer()) -> ok | {error, term()}.

Optional. Resize a running pool to Size connections.

start_pool/2

-callback start_pool(name(), opts()) -> {ok, pid()} | {error, term()}.

Start a pool registered under Name.

stop_pool/1

-callback stop_pool(name()) -> ok.

Stop a previously-started pool.

Functions

with_conn(Mod, Name, Fun)

-spec with_conn(module(), name(), fun((conn()) -> Result)) -> Result | {error, term()}.

Equivalent to with_conn(Mod, Name, Fun, #{}).

with_conn(Mod, Name, Fun, Opts)

-spec with_conn(module(), name(), fun((conn()) -> Result), checkout_opts()) -> Result | {error, term()}.

Lease a connection, run Fun(Conn), and check it back in.

Equivalent to:

case Mod:checkout(Name, Opts) of
    {ok, Conn, Token} ->
        try Fun(Conn) after Mod:checkin(Name, Token) end;
    {error, _} = Err ->
        Err
end.

Returns {error, Reason} if checkout fails, otherwise the value of Fun.