# Hare

Tools and abstractions to interact with AMQP servers.

## Hello world

Define a publisher:

defmodule MyPublisher do
  use Hare.Publisher

  @config [exchange: [name: "foo"]]

  def start_link(conn) do
    Hare.Publisher.start_link(__MODULE__, conn, @config, [])

  def publish(publisher, payload) do
    Hare.Publisher.publish(publisher, payload)

Define a consumer:

defmodule MyConsumer do
  use Hare.Consumer

  @config [exchange: [name: "foo"],
           queue:    [name: "bar"]]

  def start_link(conn, config) do
    Hare.Consumer.start_link(__MODULE__, conn, config, [])

  def handle_message(payload, _meta, state) do

    {:reply, :ack, state}

Publish and consume a message:

{:ok, conn} = Hare.Conn.start_link(adapter: Hare.Adapter.AMQP)

{:ok, publisher} = MyPublisher.start_link(conn)
{:ok, _consumer} = MyConsumer.start_link(conn)

MyPublisher.publish(publisher, "hello world!")
# => Prints "hello world!\n"

## Installation

If [available in Hex](, the package can be installed as:

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

    def deps do
      [{:amqp, "~> 0.1.4", hex: :amqp19},
       {:hare, "~> 0.1.9"}]

  2. Ensure `hare` is started before your application:

    def application do
      [applications: [:hare]]

## The Hare.Conn

The first step to interact with an AMQP server is to establish a connection.

The `Hare.Conn` starts a process that wraps a real connection. Starts a connection ,
monitors it, and reconnects on failure.

{:ok, conn} = Hare.Conn.start_link(adapter: Hare.Adapter.AMQP,
                                   backoff: [0, 100, 1000],
                                   config:  [host: "localhost", port: 1234])
# => {:ok, %Hare.Core.Conn{...}}

The example above shows all available options when starting a connection.

The `:adapter` option is mandatory and it specifies what adapter to use.
An adapter must implement the `Hare.Adapter` behaviour which includes functions
like connecting to the server, opening channels, declaring queues, publishing
messages, etc.

The only adapter provided is `Hare.Adapter.AMQP` that uses the `AMQP` library.
Note that in order to use the `Hare.Adapter.AMQP`, the `:amqp` must be explicitly
included as a dependency.

The `:backoff` option specifies a set of intervals to wait before retrying connection
in case of failure. It defaults to `[0, 10, 100, 1000, 5000]`.

On successive connection failures it waits successive intervals before retrying
and then keeps waiting for the last interval to retry forever.

The `:config` option will be given without modification to the adapter
`open_connection/1` function. It defaults to `[]`.

## Publisher

The simplest abstraction provided is the `Hare.Publisher`. It allows to publish
messages to a particular exchange.

It expects a connection and the exchange configuration in the following format:

config = [exchange: [name: "",
                     type: :direct,
                     opts: [durable: true]]]

The only mandatory option is `:name` specifying the name of the exchange to publish
to. `:type` defaults to `:direct`, and `:opts` defaults to `[]`.