ChoreRunner (chore_runner v0.5.0)
A framework and library for productively writing and running code "Chores".
A "Chore" can really be anything, but most commonly it is just some infrequently, manually run code which achieve a business or development goal.
For example: updating a config value in a database that does not yet have a UI (perhaps due to time constraints) is a great use for a chore. A chore could be created that accepts the desired value and runs the update query.
Usually, the alternative to this would be a direct prod-shell or prod-db connection, which is inherently insecure and dangerous. Many fast-moving startups or companies are ok with this access for developers, and that's fine.
But many companies have regulations that they must follow, or do not want to take the risk of a developer mistake while working in these environments.
In these cases, ChoreRunner allows the rapid creation, testing, and reviewing of code chores, along with a bundled UI for running them that accepts a variety of input types, with the goal of finding a "sweet spot" of safety and speed when solving such problems.
Getting Started
Add ChoreRunner
to your supervision tree, after your app's PubSub
:
children = [
{Phoenix.PubSub, [name: MyApp.PubSub]},
{ChoreRunner, [pubsub: MyApp.PubSub]},
]
Writing a chore
defmodule MyApp.MyChore do
use ChoreRunner.Chore
input :my_file, :file
def run(%{my_file: path}}) do
path
|> File.read!()
|> parse_file()
|> do_stuff()
end
end
Example of running this Chore:
iex> ChoreRunner.run_chore(MyApp.MyChore, %{my_file: file}, :infinity)
{:ok, %Chore{}}
Link to this section Summary
Functions
Returns the pubsub topic used for a specific chore, or all chores if given the atom :all
Returns the pubsub topic used for file downloads
List the currently running chores on all nodes.
Runs the given chore module as a chore.
Accepts an input map with either string or atom keys as well as a keyword list of options.
Returns a %ChoreRunner.Chore{}
struct.
Stops the provided chore by terminating both the chore task and the reporter.
Returns :ok
if successful, and :error
if not successful
Link to this section Functions
chore_pubsub_topic(arg1)
Specs
chore_pubsub_topic(ChoreRunner.Chore.t() | :all) :: String.t()
Returns the pubsub topic used for a specific chore, or all chores if given the atom :all
downloads_pubsub_topic()
Returns the pubsub topic used for file downloads
list_running_chores()
Specs
list_running_chores() :: [ChoreRunner.Chore.t()]
List the currently running chores on all nodes.
run_chore(chore_mod, input, opts \\ [])
Specs
run_chore(module(), map(), Keyword.t()) :: {:ok, ChoreRunner.Chore.t()} | {:error, any()}
Runs the given chore module as a chore.
Accepts an input map with either string or atom keys as well as a keyword list of options.
Returns a %ChoreRunner.Chore{}
struct.
Input map keys must match one of the inputs defined in the provided chore module. If not, the input under the unmatched key is discarded. Matched input will have default validations run on them, as well custom validations declared in the chore module. If any inputs fail validation, the chore will not run, and instead an error tuple will be returned. If all validations pass, the chore will then be run.
Opts
- extra_data: Map of arbitrary data to be forwarded to telemetry events and result handlers. Useful for storing chore session information, such as identifying who or what ran the chore.
- result_handler: Single arity anonymous function or MFA of a single arity function that is called once the chore is finished. The function will take the %Chore{}.
stop_chore(chore)
Specs
stop_chore(ChoreRunner.Chore.t()) :: :ok | :error
Stops the provided chore by terminating both the chore task and the reporter.
Returns :ok
if successful, and :error
if not successful