shigoto_db (shigoto v1.9.10)

View Source

Every statement shigoto runs goes through here.

The client was called from ten modules directly, which meant changing it was twenty five edits and a hope. It is one module now, and the rest of shigoto asks for a query rather than for a driver.

What a caller gets

#{command := atom(), num_rows := integer(), rows := [row()]} for a statement that ran, and {error, Reason} for one that did not, with {pgsql_error, Fields} as the reason a server refused it. That is the shape shigoto already reads everywhere.

Transactions

transaction/2 borrows one connection, runs BEGIN, calls the function, and commits or rolls back. Statements the function runs find that connection here rather than being handed it, because a job queue's transaction functions are ordinary code that calls shigoto_repo and cannot thread a connection through.

A COMMIT the server answers with ROLLBACK raises transaction_rolled_back. PostgreSQL does that when the transaction had already failed, and a job queue that reads it as success has marked jobs done that were never written - which is the same job running twice on the next poll.

Summary

Types

What went wrong. pgsql_error is the server refusing the statement.

The shape a statement answers with.

Functions

The connection holding this process's transaction on Pool, or undefined.

query/4 with the default decoding: rows as maps, column names as atoms.

Run one statement, on this process's transaction if it is inside one.

Start a listener for LISTEN, on a connection of its own.

Start a pool from shigoto's configuration.

Run Fun inside a transaction on Pool.

Types

error()

-type error() :: {pgsql_error, map()} | {socket, term()} | term().

What went wrong. pgsql_error is the server refusing the statement.

result()

-type result() :: #{command := atom(), num_rows := term(), rows := [term()]}.

The shape a statement answers with.

Functions

in_transaction(Pool)

-spec in_transaction(atom()) -> pid() | undefined.

The connection holding this process's transaction on Pool, or undefined.

query(Pool, SQL, Params)

-spec query(atom(), iodata(), [term()]) -> result() | {error, error()}.

query/4 with the default decoding: rows as maps, column names as atoms.

query(Pool, SQL, Params, Opts)

-spec query(atom(), iodata(), [term()], map()) -> result() | {error, error()}.

Run one statement, on this process's transaction if it is inside one.

Opts are minato's query options: timeout is a deadline after which the statement is cancelled on the server rather than abandoned, and the decoding options are the ones minato_protocol documents.

start_listener(Name, Config)

-spec start_listener(atom(), map()) -> {ok, pid()} | {error, term()}.

Start a listener for LISTEN, on a connection of its own.

LISTEN is session state, so it cannot share the pool: a notification is delivered to the session that registered for it, and a pooled connection would deliver it to whichever caller happened to hold it next.

start_pool(Name, Config)

-spec start_pool(atom(), map()) -> {ok, pid()} | {error, term()}.

Start a pool from shigoto's configuration.

Takes what shigoto and its users already write - host, port, database, user, password, pool_size - and gives minato what it takes.

transaction(Pool, Fun)

-spec transaction(atom(), fun(() -> Result)) -> Result.

Run Fun inside a transaction on Pool.

Nested calls join the transaction that is already open rather than starting a second one, because SQL has no nested BEGIN and the caller usually does not know whether it is nested.