README.md

![yggdrasil logo](https://raw.githubusercontent.com/gmtprime/yggdrasil/master/priv/static/yggdrasil.png)

[![Build Status](https://travis-ci.org/gmtprime/yggdrasil.svg?branch=master)](https://travis-ci.org/gmtprime/yggdrasil) [![Hex pm](http://img.shields.io/hexpm/v/yggdrasil.svg?style=flat)](https://hex.pm/packages/yggdrasil) [![hex.pm downloads](https://img.shields.io/hexpm/dt/yggdrasil.svg?style=flat)](https://hex.pm/packages/yggdrasil)

> *Yggdrasil* is an immense mythical tree that connects the nine worlds in
> Norse cosmology.

`Yggdrasil` is an agnostic publisher/subscriber. Some of the available adapters
are the following:

  * [Redis](https://github.com/gmtprime/yggdrasil_redis)
  (adapter's name `:redis`).
  * [RabbitMQ](https://github.com/gmtprime/yggdrasil_rabbitmq)
  (adapter's name `:rabbitmq`).
  * [PostgreSQL](https://github.com/gmtprime/yggdrasil_postgres)
  (adapter's name `:postgres`).
  * [Ethereum](https://github.com/etherharvest/yggdrasil_ethereum)
  (adapter's name `:ethereum`).
  * [GraphQL](https://github.com/etherharvest/yggdrasil_graphql)
  (adapter's name `:graphql`).

For more information on how to use them, check the respective repository.

## Small Example

The following example uses the Elixir distribution to send the messages:

```elixir
iex(1)> channel = %Yggdrasil.Channel{name: "channel"}
iex(2)> Yggdrasil.subscribe(channel)
iex(3)> flush()
{:Y_CONNECTED, %Yggdrasil.Channel{(...)}}
```

and to publish a for the subscribers:

```elixir
iex(4)> Yggdrasil.publish(channel, "message")
iex(5)> flush()
{:Y_EVENT, %Yggdrasil.Channel{(...)}, "message"}
```

When the subscriber wants to stop receiving messages, then it can unsubscribe
from the channel:

```elixir
iex(6)> Yggdrasil.unsubscribe(channel)
iex(7)> flush()
{:Y_DISCONNECTED, %Yggdrasil.Channel{(...)}}
```

## Channels

The struct `%Yggdrasil.Channel{}` is used for subscription and message
publishing e.g:

```elixir
%Yggdrasil.Channel{
  name: term(),        # Depends on the adapter.
  adapter: atom(),     # Adapter's name.
  transformer: atom(), # Transformer's name.
  backend: atom(),     # Backend's name.
  namespace: atom()    # Adapter's configuration namespace.
}
```

## Adapters

An adapter is a process that connects to a service and distributes its messages
among the subscribers of a channel. The following repositories have some of the
available adapters:

  * [RabbitMQ adapter](https://github.com/gmtprime/yggdrasil_rabbitmq):
  Fault-tolerant RabbitMQ adapter that handles exchange subscriptions and
  message distribution among subscribers. The name of the adapter is
  `:rabbitmq`.
  * [Redis adapter](https://github.com/gmtprime/yggdrasil_redis):
  Fault-tolerant Redis adapter that handles channel subscriptions and
  message distribution among subscribers. The name of the adapter is `:redis`.
  * [PostgreSQL adapter](https://github.com/gmtprime/yggdrasil_postgres):
  Fault-tolerant Postgres adapter that handles channel subscriptions and
  message distribution among subscribers. The name of the adapter is
  `:postgres`.
  * [Ethereum adapter](https://github.com/etherharvest/yggdrasil_ethereum):
  Fault-tolerant Ethereum adapter that handles channel subscriptions to
  Solidity contracts. The name of the adapter is `:ethereum`.
  * [GraphQL adapter](https://github.com/etherharvest/yggdrasil_graphql):
  Fault-tolerant adapter that bridges GraphQL subscriptions with Yggdrasil
  subscriptions in any adapter. The name of the adapter is `:graphql`.

For more information on how to use them, check the corresponding repository
documentation.

## Transformers

A transformer is the implementation of the behaviour `Yggdrasil.Transformer`.
In essence implements two functions:

  * `decode/2` for decoding messages coming from the adapter.
  * `encode/2` for encoding messages going to the adapter

`Yggdrasil` has two implemented transformers:

  * `:default` - Does nothing to the messages and it is the default
  transformer used if no transformer has been defined.
  * `:json` - Transforms from Elixir maps to string JSONs and viceversa.

## Backends

A backend is the implementation of the behaviour `Yggdrasil.Backend`. The
module is in charge of distributing the messages with a certain format inside
`Yggdrasil`. Currently, there is only one backend, `:default`, and it is used
by default in `:elixir` adapter and the previously mentioned adapters
`:rabbitmq`, `:redis` and `:postgres`.

The messages received by the subscribers when using `:default` backend are:

  * `{:Y_CONNECTED, %Yggdrasil.Channel{(...)}}` when the connection with the
  adapter is established.
  * `{:Y_EVENT, %Yggdrasil.Channel{(...)}, term()}` when a message is received
  from the adapter.
  * `{:Y_DISCONNECTED, %Yggdrasil.Channel{(...)}}` when the connection with the
  adapter is finished due to disconnection or unsubscription.

## Configuration

`Yggdrasil` works out of the box with no special configuration at all. However,
it is possible to configure the publisher. `Yggdrasil` uses `Phoenix.PubSub`
for message distribution and the following are the available options:

  * `pubsub_adapter` - `Phoenix.PubSub` adapter (defaults to
    `Phoenix.PubSub.PG2`).
  * `pubsub_name` - Name of the `Phoenix.PubSub` adapter (defaults to
    `Yggdrasil.PubSub`).
  * `pubsub_options` - Options of the `Phoenix.PubSub` adapter (defaults
    to `[pool_size: 1]`).

The rest of the options are for configuring the publishers and process name
registry:

  * `publisher_options` - `Poolboy` options for publishing. Controls the amount
    of connections established with the adapter service (defaults to
    `[size: 5, max_overflow: 10]`).
  * `registry` - Process name registry (defaults to`ExReg`).

For more information about configuration using OS environment variables check
the module `Yggdrasil.Settings`.

## Installation

`Yggdrasil` is available as a Hex package. To install, add it to your
dependencies in your `mix.exs` file:

```elixir
def deps do
  [{:yggdrasil, "~> 4.1"}]
end
```

## Relevant projects used

  * [`ExReg`](https://github.com/gmtprime/exreg): rich process name registry.
  * [`Poolboy`](https://github.com/devinus/poolboy): A hunky Erlang worker pool
  factory.
  * [`Jason`](https://github.com/michalmuskala/jason): JSON parsing library.
  * [`Credo`](https://github.com/rrrene/credo): static code analysis tool for
  the Elixir language.

## Author

Alexander de Sousa.

## License

`Yggdrasil` is released under the MIT License. See the LICENSE file for further
details.