CubDB.get_and_update_multi

You're seeing just the function get_and_update_multi, go back to CubDB module for more information.
Link to this function

get_and_update_multi(db, keys_to_get, fun, options \\ [])

View Source

Specs

get_and_update_multi(
  GenServer.server(),
  [key()],
  (%{optional(key()) => value()} ->
     {any(), %{optional(key()) => value()} | nil, [key()] | nil}),
  [opt]
) :: {:ok, any()} | {:error, any()}
when opt: {:timeout, timeout()}

Gets and updates or deletes multiple entries in an atomic transaction.

Gets all values associated with keys in keys_to_get, and passes them as a map of %{key => value} entries to fun. If a key is not found, it won't be added to the map passed to fun. Updates the database and returns a result according to the return value of fun. Returns {:ok, return_value} in case of success, {:error, reason} otherwise.

The function fun should return a tuple of three elements: {return_value, entries_to_put, keys_to_delete}, where return_value is an arbitrary value to be returned, entries_to_put is a map of %{key => value} entries to be written to the database, and keys_to_delete is a list of keys to be deleted.

The read and write operations are executed as an atomic transaction, so they will either all succeed, or all fail. Note that get_and_update_multi/4 blocks other write operations until it completes.

The options argument is an optional keyword list of options, including:

  • :timeout - a timeout (in milliseconds or :infinity, defaulting to 5000) for the operation, after which the function returns {:error, :timeout}. This is useful to avoid blocking other write operations for too long.

Example

Assuming a database of names as keys, and integer monetary balances as values, and we want to transfer 10 units from "Anna" to "Joy", returning their updated balance:

{:ok, {anna, joy}} = CubDB.get_and_update_multi(db, ["Anna", "Joy"], fn entries ->
  anna = Map.get(entries, "Anna", 0)
  joy = Map.get(entries, "Joy", 0)

  if anna < 10, do: raise(RuntimeError, message: "Anna's balance is too low")

  anna = anna - 10
  joy = joy + 10

  {{anna, joy}, %{"Anna" => anna, "Joy" => joy}, []}
end)

Or, if we want to transfer all of the balance from "Anna" to "Joy", deleting "Anna"'s entry, and returning "Joy"'s resulting balance:

{:ok, joy} = CubDB.get_and_update_multi(db, ["Anna", "Joy"], fn entries ->
  anna = Map.get(entries, "Anna", 0)
  joy = Map.get(entries, "Joy", 0)

  joy = joy + anna

  {joy, %{"Joy" => joy}, ["Anna"]}
end)