Current section
Files
Jump to
Current section
Files
lib/modules/mnesia_assistant/error.ex
defmodule MnesiaAssistant.Error do
alias :mnesia, as: Mnesia
require Logger
# types link https://www.erlang.org/doc/man/mnesia#data-types
@error_types [
:nested_transaction,
:badarg,
:no_transaction,
:combine_error,
:bad_index,
:already_exists,
:index_exists,
:no_exists,
:system_limit,
:mnesia_down,
:not_a_db_node,
:bad_type,
:node_not_running,
:truncated_binary_file,
:active,
:illegal
]
@doc """
### Erlang document:
All Mnesia transactions, including all the schema update functions, either return value `{atomic, Val}`
or the tuple `{aborted, Reason}`. Reason can be either of the atoms in the following list.
The function `error_description/1` returns a descriptive string that describes the error.
- `nested_transaction`. Nested transactions are not allowed in this context.
- `badarg`. Bad or invalid argument, possibly bad type.
- `no_transaction`. Operation not allowed outside transactions.
- `combine_error`. Table options illegally combined.
- `bad_index`. Index already exists, or was out of bounds.
- `already_exists`. Schema option to be activated is already on.
- `index_exists`. Some operations cannot be performed on tables with an index.
- `no_exists`. Tried to perform operation on non-existing (not-alive) item.
- `system_limit`. A system limit was exhausted.
- `mnesia_down`. A transaction involves records on a remote node, which became unavailable
before the transaction was completed. Records are no longer available elsewhere in the network.
- `not_a_db_node`. A node was mentioned that does not exist in the schema.
- `bad_type`. Bad type specified in argument.
- `node_not_running`. Node is not running.
- `truncated_binary_file`. Truncated binary in file.
- `active`. Some delete operations require that all active records are removed.
- `illegal`. Operation not supported on this record.
Error can be Reason, `{error, Reason}`, or `{aborted, Reason}`. Reason can be an atom or a
tuple with Reason as an atom in the first field.
The following examples illustrate a function that returns an error, and the method to
retrieve more detailed error information:
- The function `mnesia:create_table(bar, [{attributes, 3.14}])` returns the tuple `{aborted,Reason}`, where
Reason is the tuple `{bad_type,bar,3.14000}`.
The function `mnesia:error_description(Reason)` returns the term `{"Bad type on some provided arguments",bar,3.14000}`,
which is an error description suitable for display.
- `error_description(Error :: term())`
### Example:
```elixir
MnesiaAssistant.Error.error_description(error)
```
"""
def error_description(error), do: Mnesia.error_description(error)
def error_description(error, identifier) when error in [{:atomic, :ok}, :ok] do
Logger.info(
"Identifier: #{inspect(identifier)} ::: MnesiaMessage: The action concerned was completed successfully."
)
{:ok, :atomic}
end
def error_description(:starting, identifier) do
Logger.info(
"Identifier: #{inspect(identifier)} ::: MnesiaMessage: The action concerned is being started successfully."
)
{:ok, :atomic}
end
def error_description({:aborted, {:already_exists, _module}} = error, identifier) do
converted = error_description(error)
Logger.warning(
"Identifier: #{inspect(identifier)} ::: MnesiaError: #{inspect(error)} ::: ConvertedError: #{inspect(converted)}"
)
err = if is_tuple(converted), do: to_string(elem(converted, 0)), else: converted
{:error, error, err}
end
def error_description({:error, {_, {:already_exists, _}}} = error, identifier) do
converted = error_description(error)
Logger.warning(
"Identifier: #{inspect(identifier)} ::: MnesiaError: #{inspect(error)} ::: ConvertedError: #{inspect(converted)}"
)
err = if is_tuple(converted), do: to_string(elem(converted, 0)), else: converted
{:error, error, err}
end
def error_description({:aborted, error_type} = error, identifier) when is_tuple(error_type) do
if elem(error_type, 0) in @error_types do
converted = error_description(error)
Logger.error(
"Identifier: #{inspect(identifier)} ::: MnesiaError: #{inspect(error)} ::: ConvertedError: #{inspect(converted)}"
)
err = if is_tuple(converted), do: to_string(elem(converted, 0)), else: converted
{:error, error, err}
else
error_description(error, identifier)
end
end
def error_description(error, identifier) do
converted = error_description(error)
Logger.error(
"Identifier: #{inspect(identifier)} ::: MnesiaError: #{inspect(error)} ::: ConvertedError: #{inspect(converted)}"
)
{:error, error, converted}
end
def try?({:error, {:timeout, _missing_tables}, _}, max, current) when current <= max, do: true
def try?({:error, {:timeout, _missing_tables}, _}, max, current) when current > max, do: false
def try?({:ok, :atomic}, _max, _current), do: false
def try?(_error, _max, _current), do: false
def try?({:error, {:timeout, _missing_tables}, _}), do: true
def try?({:ok, :atomic}), do: false
def try?(_error), do: false
end