Packages
honeydew
0.0.1
1.5.0
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-rc7
1.0.0-rc6
1.0.0-rc5
1.0.0-rc4
1.0.0-rc3
1.0.0-rc2
1.0.0-rc1
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
Pluggable local/clusterable job queue focused on safety.
Current section
Files
Jump to
Current section
Files
README.md
Honeydew
========
Honeydew (["Honey, do!"](http://en.wiktionary.org/wiki/honey_do_list)) is a job queue library for Elixir.
- Workers ("Honeys") are permanent and hold immutable state.
- Honeys pull jobs from the work queue ("Job List").
- Tasks are executed using `cast/1` and `call/2`, somewhat like a `GenServer`.
- If a Honey crashes while processing a job, the job is recovered and placed back on the queue.
## Usage
Simply create a module and `use Honeydew`, then start the pool with `YourModule.start_pool/2`.
You can request tasks be processed using `cast/1` or `call/2`, like so:
`Your.Module.cast({:insert_thing_in_db, ["key", "value"]})`
`Your.Module.call({:get_thing_from_db, ["key"]}) # -> "value"`
## Example
```elixir
# This is your worker
defmodule CatFeedingHoney do
use Honeydew
def init(pantry_location) do
Pantry.init(pantry_location)
end
# the last argument is always the honey's state
def make_snack(kind, kitty, pantry) do
snack = Pantry.get(pantry, :snacks, kind)
"#{snack} snack for #{kitty}!"
end
def go_shopping(pantry) do
Pantry.put(pantry, :snacks, :tuna)
IO.puts("went shopping")
end
end
# This is your database
defmodule Pantry do
def init(_location) do
{:ok, :pantry_connection}
end
def get(_pantry_connection, _shelf, item) do
item
end
def put(_pantry_connection, _shelf, item) do
item
end
end
CatFeedingHoney.start_pool("kitchen")
#
# Blocking call
#
CatFeedingHoney.call(:make_snack, [:tuna, :darwin]) # -> "tuna snack for darwin!"
#
# Non-blocking cast
#
CatFeedingHoney.cast(:go_shopping) # -> prints "went shopping"
#
# You can pass arbitrary functions to be executed, too.
#
CatFeedingHoney.call(fn(pantry) -> IO.inspect pantry end) # -> :pantry_connection
```
## Worker State
Worker State itself is immutable, the only way to change it is to cause the worker to crash and restart.
Your worker module's `init/1` function must return `{:ok, state}`. If anything else is returned or the function raises an error, the worker will die and restart after a given time interval (by default, five seconds).
## Configuration
### Worker Respawn Delay
You can configure the worker module's respawn delay time, in case `init/1` fails, like so:
`Your.Module.start_pool([:some_worker_args], init_retry_secs: 20)`
### Maximum Failures
Jobs are only allowed to fail a certain number of times before they are no longer retried (default, three times), this is also configurable via `start_pool/1`:
`Your.Module.start_pool([:some_worker_args], max_failures: 5)`
(at present, jobs that fail too much are abandoned, but in the future will be written to disk)
### Number of Workers
Honeydew will supervise the number of workers you specify (default, ten worker)
`Your.Module.start_pool[:some_worker_args], workers: 50)`
## Process Tree
After calling `Your.Module.start_pool/2`, a process tree like this will be created under the supervision of Honeydew:
```
Honeydew.Supervisor
└── Honeydew.Your.Module.HomeSupervisor
├── Honeydew.Your.Module.JobList
└── Honeydew.Your.Module.HoneySupervisor
├── Honeydew.Honey
├── Honeydew.Honey
├── Honeydew.Honey
└── Honeydew.Honey
```
## Disclaimer
This library is under active development, please don't use it in production yet, and please contribute if you find it useful! :)
## Acknowledgements
Thanks to @marcelog, for his [failing worker restart strategy](http://inaka.net/blog/2012/11/29/every-day-erlang/).