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:
:elixir
adapter: It’s the default adapter and uses the message distribution built in Erlang/Elixir.:redis
adapter: It’s the provided adapter for Redis.:postgres
adapter: It’s the provided adapter for Postgres.:rabbitmq
adapter: 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:
:elixir
adapter: Can be any Erlang/Elixirterm()
.:redis
adapter: Should be abinary()
without spaces.:postgres
adapter: Should be a alphanumericbinary()
.:rabbitmq
adapter: 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
:
:default
transformer: Does nothing to the messages.:json
transformer: 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 arepoolboy
options 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.PubSub
adapter (defaults toPhoenix.PubSub.PG2
).pubsub_name
- Name of thePhoenix.PubSub
adapter (defaults toYggdrasil.PubSub
).pubsub_options
- Options of thePhoenix.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 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
.