README.md

# JobQueue

[![Build Status](https://travis-ci.org/jeffutter/job_queue.svg?branch=master)](https://travis-ci.org/jeffutter/job_queue)
[![Hex.pm](https://img.shields.io/hexpm/v/job_queue.svg?maxAge=2592000)](https://hex.pm/packages/job_queue)
[![Inline docs](http://inch-ci.org/github/jeffutter/job_queue.svg)](http://inch-ci.org/github/jeffutter/job_queue)
[![Deps Status](https://beta.hexfaktor.org/badge/all/github/jeffutter/job_queue.svg)](https://beta.hexfaktor.org/github/jeffutter/job_queue)
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)


JobQueue is a small library for building job queues in Elixir. It is based on GenStage and erlang :queues.

The goal of the library is to simplify creation of queues with both single and multiple steps, as well as retrying of individual steps and deduplication of events.

## Example Use Case

JobQueue allows building complex workflows such as:

**Image Resizer**
* Queue a job with a link to an image to download
* Master Queue
  * This queue can deduplicate urls so that it won't re-download an image that is already being processed
  * This queue can also re-try if any sub-jobs fail
  * This queue is broken down to the following steps:
    * Step 1: Download the image
      * With one download queue, this can limit the total number of simultaneous downloads 
      * Abort entire pipeline if download fails
    * Step 2: Fan out jobs to resize the image to multiple sizes
      * Limit the number of simultaneous resizes
      * Abort all sizes if one resize fails
    * Step 3: Upload each size to another S3 Bucket
      * Limit the number of simultaneous downloads
      * Retry upload on failure
    * Step 4: Cleanup
      * Cleanup on failures or success
      * Acknowledge job to Master Queue
  * Retry the whole job depending on the nature of sub-job failures

## Installation

Add `job_queue` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:job_queue, "~> 0.1.0"}
  ]
end
```

## Documentation

Full documentation can be found on hexdocs at [https://hexdocs.pm/job_queue/](https://hexdocs.pm/job_queue/)

## Quick Start

Write a Worker module to handle your events:

```elixir
defmodule Worker do
  use JobQueue.Worker

  def handle_event(event) do
    IO.inspect(event)
    {:ok, event}
  end
end
```

Start the Queue and Processor:

```elixir
{:ok, _queue} = JobQueue.Queue.start_link(MyQueue)
{:ok, _processor} = JobQueue.Processor.start_link(MyQueue, Worker)
```

Add some work to the Queue:

```elixir
JobQueue.Queue.add_sync(MyQueue, :done)
#=> :done
```

You can also start the queue and processor from a supervisor:

```elixir
defmodule MyApp.Application do
  @moduledoc false

  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(JobQueue.Queue, [MyQueue], id: MyQueue),
      worker(JobQueue.Processor, [MyQueue, MyWorker], id: MyWorker),
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```