Simple background job backed by PostgreSQL for Elixir.
NOTE: Backy is still in very early stage of development and might not be stable yet.
The package can be installed as:
mix.exs
:def deps do
[{:backy, "~> 0.0.16"}]
end
def application do
[applications: [:backy]]
end
In your config.exs
:
# Default configuration
config :backy, :db,
database: "backy"
The :db
hash is passed directly to Postgrex.start_link/1
( https://hexdocs.pm/postgrex/Postgrex.html#start_link/1 ).
You can specify any supported option
# Default configuration
config :backy,
table_name: "jobs", # The postgresql table name
retry_count: 3, # The number of retry for a job before marking it as failed
retry_delay: fn (retry) -> :math.pow(retry, 3) + 100 end, # Retry delay
poll_interval: 1000, # Polling interval for the job poller
# If false, jobs will be marked as finished, otherwise they are deleted
# If false, you are responsible for purging the jobs table
delete_finished_jobs: true
To create the job table, run:
mix backy.setup
If you use backy with ecto/phoenix, you may include backy mix tasks
in ecto.reset
like so:
defp aliases do
["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"test": ["ecto.create --quiet", "ecto.migrate", "test"],
"ecto.reset": ["ecto.drop", "ecto.create", "backy.setup", "ecto.setup"]]
end
IMPORTANT: Jobs will always receive maps instead of keyword list, because of JSON serialization, the order of key is not guaranteed, for this reason all the keyword lists are converted to maps.
defmodule TestWorker do
use Backy.Worker,
# If the job `perform` takes more than 20 sec, kill it
# default to 1000 (1sec)
max_runtime: 20000,
# Max concurrency, default to `:unlimited`
max_concurrency: 2,
# When a job is stuck (for example, beam crashed), wait 10 sec before
# queuing it again, default to 10000 (10sec)
requeue_delay: 20000
# The following example runs for 30 sec while the max runtime is 20 sec
def perform(%Backy.Job{} = job, %{name: name}) do
IO.puts("Job started for #{name}")
:timer.sleep(10000) # Simulate work for 10 sec
# We have still work to do, max runtime is 20sec, avoid a timeout
Backy.touch(job)
:timer.sleep(10000) # Simulate work for 10 sec
# We have still work to do, max runtime is 20sec, avoid a timeout
Backy.touch(job)
:timer.sleep(10000) # Simulate work for 10 sec
IO.puts("Job finished")
end
end
job = Backy.enqueue(TestWorker, name: "foo bar")
Copyright ©2016 Nicolas Goy
This library is loosely inspired by:
MIT