Packages

A chaos engineering library for Elixir that makes functions return errors based on configurable failure rates.

Current section

Files

Jump to
mutineer lib failures.ex
Raw

lib/failures.ex

defmodule Mutineer.Failures do
@doc """
Triggers a failure of the specified type.
"""
def trigger_failure(:error, _func, opts), do: error_failure(opts[:errors] || opts[:error])
def trigger_failure(:raise, _func, opts),
do: raise_failure(opts[:raised_errors] || opts[:raised_error], opts)
def trigger_failure(:delay, func, opts), do: delay_failure(func, opts[:delay])
def trigger_failure(nil, _func, _opts), do: nil
def trigger_failure(:exit, _func, opts),
do: exit_failure(opts[:exit_errors] || opts[:exit_error])
def trigger_failure(:timeout, _func, opts),
do: timeout_failure(opts[:delay], opts[:raised_errors] || opts[:raised_error], opts)
defp error_failure(nil), do: {:error, :mutineer_chaos}
defp error_failure(errors) when is_list(errors), do: Enum.random(errors)
defp error_failure(error), do: error
defp raise_failure(nil, opts) do
raise Mutineer.ChaosError,
message: opts[:message] || "Mutiny!",
function: opts[:function],
module: opts[:module]
end
defp raise_failure(raised_errors, opts) when is_list(raised_errors) do
raise Enum.random(raised_errors),
message: opts[:message] || "Mutiny!",
function: opts[:function],
module: opts[:module]
end
defp raise_failure(error, opts) do
raise error,
message: opts[:message] || "Mutiny!",
function: opts[:function],
module: opts[:module]
end
defp delay_failure(func, %Range{} = delay) do
delay
|> Enum.random()
|> Process.sleep()
func.()
end
defp delay_failure(func, delay) when is_nil(delay) or is_integer(delay) do
delay = delay || :rand.uniform(4000) + 1000
Process.sleep(delay)
func.()
end
defp delay_failure(func, %Range{} = delay) do
delay
|> Enum.random()
|> Process.sleep()
func.()
end
defp timeout_failure(%Range{} = delay, raised_errors, opts) do
delay
|> Enum.random()
|> Process.sleep()
raise_failure(raised_errors, opts)
end
defp timeout_failure(delay, raised_errors, opts) when is_nil(delay) or is_integer(delay) do
delay = delay || :rand.uniform(4000) + 1000
Process.sleep(delay)
raise_failure(raised_errors, opts)
end
defp exit_failure(exit_errors) when is_list(exit_errors) do
exit_errors
|> Enum.random()
|> exit()
end
defp exit_failure(nil), do: exit(:mutineer_chaos)
defp exit_failure(exit_error), do: exit(exit_error)
end