BitcrowdEcto.Repo behaviour (bitcrowd_ecto v0.12.0) View Source

Extensions for Ecto repos.

Usage

defmodule MyApp.Repo do
  use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres

  use BitcrowdEcto.Repo
end

Link to this section Summary

Callbacks

Acquires an advisory lock for a named resource.

Allows to conveniently count a queryable.

Fetches a record by ID or returns a "tagged" error tuple.

Fetches a record by ID or returns a "tagged" error tuple.

Fetches a record by given clauses or returns the result wrapped in an ok tuple.

Fetches a record by given clauses or returns the result wrapped in an ok tuple.

Link to this section Types

Specs

fetch_option() ::
  {:lock, :no_key_update | :update | false} | {:preload, atom() | list()}

Specs

fetch_result() ::
  {:ok, Ecto.Schema.t()} | {:error, {:not_found, Ecto.Queryable.t()}}

Specs

lock_mode() :: :no_key_update | :update

Link to this section Callbacks

Link to this callback

advisory_xact_lock(arg1)

View Source (since 0.1.0)

Specs

advisory_xact_lock(atom() | binary()) :: :ok

Acquires an advisory lock for a named resource.

Advisory locks are helpful when you don't have a specific row to lock, but also don't want to lock an entire table.

See https://www.postgresql.org/docs/9.4/explicit-locking.html#ADVISORY-LOCKS

Example

MyApp.Repo.transaction(fn ->
  MyApp.Repo.advisory_lock(:foo)
  # Advisory lock is held until end of transaction
end)

A note on the advisory lock key

pg_advisory_xact_lock() has two versions: One which you pass a 64-bit signed integer as the lock key, and one which you pass two 32-bit integers as the keys (e.g., one "application" key and one specific lock key), in which case PostgreSQL concatenates them into a 64-bit value. In any case you need to pass integers.

We decided that we wanted to have atom or string keys for better readability. Hence, in= order to make PostgreSQL happy, we hash these strings into 64 bits signed ints.

64 bits make a pretty big number already, so it is quite unlikely that two of our keys (or keys of other libraries that use advisory locks, e.g. Oban) collide. But for an extra false sense of safety we use a crypto hash algorithm to ensure that keys spread out over the domain uniformly. Luckily, taking a prefix of a cryptographic hash does not break its uniformity.

Link to this callback

count(queryable)

View Source (since 0.1.0)

Specs

count(queryable :: Ecto.Queryable.t()) :: non_neg_integer()

Allows to conveniently count a queryable.

Link to this callback

fetch(schema, id)

View Source (since 0.1.0)

Specs

fetch(schema :: module(), id :: binary()) :: fetch_result()

Fetches a record by ID or returns a "tagged" error tuple.

See fetch/2.

Link to this callback

fetch(schema, id, list)

View Source (since 0.1.0)

Specs

fetch(schema :: module(), id :: binary(), [fetch_option()]) :: fetch_result()

Fetches a record by ID or returns a "tagged" error tuple.

See fetch_by/3 for options.

Link to this callback

fetch_by(queryable, clauses)

View Source (since 0.1.0)

Specs

fetch_by(queryable :: Ecto.Queryable.t(), clauses :: map() | keyword()) ::
  fetch_result()

Fetches a record by given clauses or returns the result wrapped in an ok tuple.

See fetch_by/3.

Link to this callback

fetch_by(queryable, clauses, list)

View Source (since 0.1.0)

Specs

fetch_by(queryable :: Ecto.Queryable.t(), clauses :: map() | keyword(), [
  fetch_option()
]) :: fetch_result()

Fetches a record by given clauses or returns the result wrapped in an ok tuple.

On error, a "tagged" error tuple is returned that contains the original queryable or module as the tag, e.g. {:error, {:not_found, Account}} for a fetch_by(Account, id: 1) call.

This function can also apply row locks.

Options

  • lock any of [:no_key_update, :update] (defaults to false)
  • preload allows to preload associations