defmodule Ash.Resource.Change.OptimisticLock do
@moduledoc """
Performs an optimistic lock on the changeset.
See `Ash.Resource.Change.Builtins.optimistic_lock/1` for more.
"""
use Ash.Resource.Change
require Ash.Expr
@impl true
def change(changeset, opts, _context) do
Ash.Changeset.filter(changeset, %{
opts[:attribute] => Map.get(changeset.data, opts[:attribute])
})
end
@impl true
def atomic(changeset, opts, _context) do
case changeset.data do
%Ash.Changeset.OriginalDataNotAvailable{} ->
{:not_atomic,
"Cannot use `optimistic_lock` when updating a query, because we must know the previous version."}
data ->
{:atomic,
%{
opts[:attribute] =>
Ash.Expr.expr(
if ref(^opts[:attribute]) == ^Map.get(data, opts[:attribute]) do
ref(^opts[:attribute]) + 1
else
error(Ash.Error.Changes.StaleRecord, %{
resource: changeset.resource,
filters: %{
^opts[:attribute] => ^Map.get(data, opts[:attribute])
}
})
end
)
}}
end
end
end