forked from oban-bg/oban
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce Plugin behaviour and expand plugin option validation (oban-…
…bg#659) A new `Oban.Plugin` behavior simplifies and unifies the process of testing plugins. Co-authored-by: Milton Mazzarri <me@milmazz.uno>
- Loading branch information
Showing
18 changed files
with
567 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
defmodule Oban.Plugin do | ||
@moduledoc """ | ||
Defines a shared behaviour for Oban plugins. | ||
In addition to implementing the Plugin behaviour, all plugins **must** be a `GenServer`, `Agent`, or | ||
another OTP compliant module. | ||
## Example | ||
Defining a basic plugin that satisfies the minimum: | ||
defmodule MyPlugin do | ||
@behaviour Oban.Plugin | ||
use GenServer | ||
@impl Oban.Plugin | ||
def start_link(opts) do | ||
GenServer.start_link(__MODULE__, opts, name: opts[:name]) | ||
end | ||
@impl Oban.Plugin | ||
def validate(opts) do | ||
if is_atom(opts[:mode]) | ||
:ok | ||
else | ||
{:error, "expected opts to have a :mode key"} | ||
end | ||
end | ||
@impl GenServer | ||
def init(opts) do | ||
case validate(opts) do | ||
:ok -> {:ok, opts} | ||
{:error, reason} -> {:stop, reason} | ||
end | ||
end | ||
end | ||
""" | ||
|
||
alias Oban.Config | ||
|
||
@type option :: {:conf, Config.t()} | {:name, GenServer.name()} | {atom(), term()} | ||
@type validator :: (option() -> :ok | {:error, term()}) | ||
|
||
@doc """ | ||
Starts a Plugin process linked to the current process. | ||
Plugins are typically started as part of an Oban supervision tree and will receive the current | ||
configuration as `:conf`, along with a `:name` and any other provided options. | ||
""" | ||
@callback start_link([option()]) :: GenServer.on_start() | ||
|
||
@doc """ | ||
Validate the structure, presence, or values of keyword options. | ||
""" | ||
@callback validate([option()]) :: :ok | {:error, term()} | ||
|
||
@doc """ | ||
A utility to help validate options without resorting to `throw` or `raise` for control flow. | ||
## Example | ||
Ensure all keys are known and the correct type: | ||
validate(opts, fn | ||
{:conf, conf} when is_struct(conf) -> :ok | ||
{:name, name} when is_atom(name) -> :ok | ||
opt -> {:error, "unknown option: " <> inspect(opt)} | ||
end) | ||
""" | ||
@spec validate([option()], validator()) :: :ok | {:error, term()} | ||
def validate(opts, validator) do | ||
Enum.reduce_while(opts, :ok, fn opt, acc -> | ||
case validator.(opt) do | ||
:ok -> {:cont, acc} | ||
{:error, _reason} = error -> {:halt, error} | ||
end | ||
end) | ||
end | ||
|
||
@doc false | ||
@spec validate!([option()], ([option()] -> :ok | {:error, term()})) :: :ok | ||
def validate!(opts, validate) do | ||
with {:error, reason} <- validate.(opts), do: raise(ArgumentError, reason) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.