yggdrasil v3.3.1 Yggdrasil View Source
Yggdrasil is an immense mythical tree that connects the nine worlds in Norse cosmology.
Yggdrasil is an agnostic publisher/subscriber for (but not exclusively)
Redis, RabbitMQ, PostgreSQL and Elixir process messaging.

Small Example
The following example uses the Elixir distribution to send the messages. It is equivalent to the Redis, RabbitMQ and Postgres distributions when a connection configuration is supplied:
iex(1)> channel = %Yggdrasil.Channel{name: "channel"}
iex(2)> Yggdrasil.subscribe(channel)
iex(3)> flush()
{:Y_CONNECTED, _}
and to publish a for the subscribers:
iex(4)> Yggdrasil.publish(channel, "message")
iex(5)> flush()
{:Y_EVENT, _, "message"}
When the subscriber wants to stop receiving messages, then it can unsubscribe from the channel:
iex(6)> Yggdrasil.unsubscribe(channel)
iex(7)> flush()
{:Y_DISCONNECTED, _}
Overview
This library provides three functions i.e:
Subscribing to a channel:
Yggdrasil.subscribe(Yggdrasil.Channel.t()) :: :ok | {:error, term()}The process that subscribes will receive the following message when the adapter has connected successfully:
{:Y_CONNECTED, Yggdrasil.Channel.t()}Unsubscribing from a channel:
Yggdrasil.unsubscribe(Yggdrasil.Channel.t()) :: :ok | {:error, term()}The process that was subscribed to the channel will receive the following message when the adapter has disconnected successfully:
{:Y_DISCONNECTED, Yggdrasil.Channel.t()}Publishing in a channel:
Yggdrasil.publish(Yggdrasil.Channel.t(), message()) :: :ok | {:error, term()} when message: term()The processes that are subscribed to the channel will receive the following message:
{:Y_EVENT, Yggdrasil.Channel.t(), message()} when message: term()
Channels
The channels can be defined with the structure Yggdrasil.Channel.t(), i.e:
@type t :: %Yggdrasil.Channel{
adapter: adapter(),
name: channel(),
transformer: transformer(),
namespace: namespace()
}
Channel adapter
It’s the adapter to be used for subscriptions and/or publishing. The available adapters are:
:elixiradapter: It’s the default adapter and uses the message distribution built in Erlang/Elixir.:redisadapter: It’s the provided adapter for Redis.:postgresadapter: It’s the provided adapter for Postgres.:rabbitmqadapter: It’s the provided adapter for RabbitMQ.
Custom adapters can be implemented and used by setting adapter to the module
of the custom adapter.
Channel name
It’s the name of the channel. Depending on the adapter there are limitations in how the name can be. For the provided adapters, the names can be as follows:
:elixiradapter: Can be any Erlang/Elixirterm().:redisadapter: Should be abinary()without spaces.:postgresadapter: Should be a alphanumericbinary().:rabbitmqadapter: Should be a tuple{exchange(), routing_key()}whereexchange()androuting_key()arebinary().
Channel transformer
It’s a module that encodes the messages published in a channel and decodes the
messages coming from a channel. There are two transformers provided with
Yggdrasil:
:defaulttransformer: Does nothing to the messages.:jsontransformer: Encodesmap()to JSONbinary()and decodes JSONbinary()asmap().
Apart from the transformers provided it’s possible to define custom
transformers to decode and encode messages from and to the adapters
respectively e.g by using a libray like
Poison (:json uses Jason library) we
can define the following transformer:
defmodule JSONTransformer do
use Yggdrasil.Transformer
alias Yggdrasil.Channel
def decode(%Channel{} = _channel, message) do
Poison.decode(message)
end
def encode(%Channel{} = _channel, data) when is_map(data) do
Poison.encode(data)
end
end
Then declaring the channel using JSONTransformer with the Redis adapter would
be:
and using the RabbitMQ adapter the channel would be:
iex(1)> channel = %Yggdrasil.Channel{
...(1)> name: "redis_channel",
...(1)> adapter: :redis,
...(1)> transformer: JSONTransformer
...(1)> }
Channel namespace
By default, all the namespaces are Yggdrasil, but if, for example, you have
several different Redis servers you want to subscribe, you can use the
namespaces in the configuration to differentiate them e.g:
use Mix.Config
config :yggdrasil, RedisOne,
redis: [hostname: "redis.one"]
config :yggdrasil, RedisTwo,
redis: [hostname: "redis.two"]
Configuration
Yggdrasil works out of the box with no special configuration at all.
Although all the adapters try to connect with the different services using the default credentials, custom connection configurations can be set with or without namespaces.
Redis Configuration
Uses the list of options of Redix, but the more relevant options are shown
below:
hostname- Redis hostname (defaults to"localhost").port- Redis port (defaults to6379).password- Redis password (defaults to"").
The following shows a configuration with and without namespace:
# Without namespace
config :yggdrasil,
redis: [hostname: "redis.zero"]
# With namespace
config :yggdrasil, RedisOne,
redis: [
hostname: "redis.one",
port: 1234
]
RabbitMQ Configuration
Uses the list of options of AMQP, but the more relevant options are shown
below:
hostname- RabbitMQ hostname (defaults to"localhost").port- RabbitMQ port (defaults to5672)username- Username (defaults to"guest").password- Password (defaults to"guest").virtual_host- Virtual host (defaults to"/").subscriber_options- Controls the amount of connections established with RabbitMQ. These arepoolboyoptions for RabbitMQ subscriber (defaults to[size: 5, max_overflow: 10]).
The following shows a configuration with and without namespace:
# Without namespace
config :yggdrasil,
rabbitmq: [hostname: "rabbitmq.zero"]
# With namespace
config :yggdrasil, RabbitMQOne,
rabbitmq: [
hostname: "rabbitmq.one",
port: 1234
]
Postgres Configuration
Uses the list of options of Postgrex, but the more relevant options are shown
below:
hostname- Postgres hostname (defaults to"localhost")port- Postgres port (defaults to5432).username- Postgres username (defaults to"postgres").password- Postgres password (defaults to"postgres").database- Postgres database name (defaults to"postgres").
The following shows a configuration with and without namespace:
# Without namespace
config :yggdrasil,
postgres: [password: "some password"]
# With namespace
config :yggdrasil, PostgresOne,
postgres: [
password: "some other password"
]
Message Distribution Configuration
Yggdrasil uses Phoenix.PubSub for the message distribution. The following
options show how to configure it:
pubsub_adapter-Phoenix.PubSubadapter (defaults toPhoenix.PubSub.PG2).pubsub_name- Name of thePhoenix.PubSubadapter (defaults toYggdrasil.PubSub).pubsub_options- Options of thePhoenix.PubSubadapter (defaults to[pool_size: 1]).
The rest of the options are for configuring the publishers and process name registry:
publisher_options-Poolboyoptions for publishing. Controls the amount of connections established with the service (defaults to[size: 5, max_overflow: 10]).registry- Process name registry (defaults toExReg).
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:
def deps do
[{:yggdrasil, "~> 3.3"}]
end
and ensure Yggdrasil is started before your application:
def application do
[applications: [:yggdrasil]]
end
Link to this section Summary
Functions
Publishes a message in a channel with some optional options
Subscribes to a channel
Unsubscribes from a channel
Link to this section Functions
publish(Yggdrasil.Channel.t(), term(), Keyword.t()) :: :ok | {:error, term()}
Publishes a message in a channel with some optional options.
subscribe(Yggdrasil.Channel.t()) :: :ok | {:error, term()}
Subscribes to a channel.
unsubscribe(Yggdrasil.Channel.t()) :: :ok | {:error, term()}
Unsubscribes from a channel.