ExOperation v0.5.0 ExOperation.DSL View Source

Functions that help defining operations.

Link to this section Summary

Functions

Schedules a callback function to run after successful database transaction commit

Schedules a callback function to run before database transaction start

Changes operation’s scenario depending on results of previous steps using callback

A conveniece step for fetching entities from the database. It wraps Ecto.Repo.get/2 under the hood

Adds an arbitrary step to the operation pipeline

Embeds another operation into the current one

Link to this section Types

Link to this section Functions

Link to this function after_commit(operation, callback) View Source
after_commit(
  operation :: ExOperation.Operation.t(),
  callback :: (txn() -> {:ok, txn()} | {:error, term()})
) :: ExOperation.Operation.t()

Schedules a callback function to run after successful database transaction commit.

The callback receives the transaction map and must return {:ok, txn} or {:error, reason} like step/2’s callback does.

All hooks are applied in the same order they were added.

Link to this function before_transaction(operation, callback) View Source
before_transaction(
  operation :: ExOperation.Operation.t(),
  callback :: (txn() -> {:ok, txn()} | {:error, term()})
) :: ExOperation.Operation.t()

Schedules a callback function to run before database transaction start.

The callback receives the transaction map and must return {:ok, txn} or {:error, reason} like step/2’s callback does.

All hooks are applied in the same order they were added.

Before transaction hooks are not allowed to be defined in suboperations and defers since the transaction is already started at the moment of the execution. This will raise ExOperation.AssertionError an error in runtime.

Since before transactions hooks can’t be used in suboperations operations that use them lose their composability feature so don’t overuse this kind of callbacks. Make sure that it will always be a top-level operation.

If you want to make a before transaction callback in a suboperation or defer consider splitting up the operation in two. Put an after commit callback into your first part that schedules an asynchronous task that does what you wanted to do in between and then runs the second operation.

Link to this function defer(operation, callback) View Source
defer(
  operation :: ExOperation.Operation.t(),
  callback :: (ExOperation.Operation.t(), txn() -> ExOperation.Operation.t())
) :: ExOperation.Operation.t()

Changes operation’s scenario depending on results of previous steps using callback.

The callback receives the operation and results of previous steps. It must return a new operation.

Link to this function find(operation, name, opts) View Source
find(operation :: ExOperation.Operation.t(), name :: name(), opts :: keyword()) ::
  ExOperation.Operation.t()

A conveniece step for fetching entities from the database. It wraps Ecto.Repo.get/2 under the hood.

Options

  • :schema – an Ecto.Schema module name to find for. This options is required.
  • :id_path – param name or path list for deeply nested id key. Defaults to [:id].
  • :preloads – a list of association preloading in the format of Ecto.Repo.preload/3. Doesn’t preload any associations by default.
  • :optional – when enabled doesn’t return error but nil if :id_path is missing in the given params. Defaults to false.
  • :skip_missing – when enabled doesn’t return error but nil if the entity is missing in the database. Defaults to false.
  • :context_getter – an optional function that gets the context and returns {:ok, schema}, :not_found, or {:error, reason}. If :not_found is returned then it tries to find the schema in the database as usual.
Link to this function step(operation, name, callback) View Source
step(
  operation :: ExOperation.Operation.t(),
  name :: name(),
  callback :: (txn :: txn() -> {:ok | :error, any()})
) :: ExOperation.Operation.t()

Adds an arbitrary step to the operation pipeline.

callback is a function that accepts a map of changes so far where keys are names of previous steps and values are their return values. It must return either {:ok, result} or {:error, reason} tuple.

Don’t do long (or potentially long such as calling external services) things in steps as they are runned inside a database transaction. You may catch a timeout or slow down the database’s performance. Instead consider introducing an intermediate database state and splitting the operation in two. Run the first part of the logic, in after commit callback schedule an asynchronous task that runs the slow thing and then runs the second part in another transaction.

Link to this function suboperation(operation, module, params_or_fun, opts \\ []) View Source
suboperation(
  operation :: ExOperation.Operation.t(),
  module :: atom(),
  params_or_fun :: map() | (txn :: txn() -> map()),
  opts :: keyword()
) :: ExOperation.Operation.t()

Embeds another operation into the current one.

module is the suboperation module.

params_or_fun can be either a map or a callback function that gets changes so far and returns a map. The map will be passed to the suboperation.

Context is passed without changes.

Options

  • :id – unique term to identify the suboperation (optional).
  • :context – override context (optional). It can be a map or a function that gets current transaction map and returns a context map to pass into the suboperation.