Skip to content

Instantly share code, notes, and snippets.

@todd
Created April 25, 2016 02:32
Show Gist options
  • Save todd/105519c57ef176336e135fa1ad4e4e6c to your computer and use it in GitHub Desktop.
Save todd/105519c57ef176336e135fa1ad4e4e6c to your computer and use it in GitHub Desktop.
Redis Keyevents -> RabbitMQ Messages
# mix.exs
defmodule RedisRabbitElixir.Mixfile do
use Mix.Project
def project do
[app: :redis_rabbit_elixir,
version: "0.0.1",
elixir: "~> 1.2",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps]
end
# Configuration for the OTP application
#
# Type "mix help compile.app" for more information
def application do
[applications: [:logger, :amqp, :redix]]
end
# Dependencies can be Hex packages:
#
# {:mydep, "~> 0.3.0"}
#
# Or git/path repositories:
#
# {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
#
# Type "mix help deps" for more examples and options
defp deps do
[
{:amqp, "~> 0.1.4"},
{:redix, "~> 0.3.6"}
]
end
end
# lib/redis_rabbit_elixir.ex
# Demo implementation of an Elixir GenServer that will subscribe to Redis
# Key events and forward the affected key name to RabbitMQ.
#
# Run instructions:
#
# Install Rabbitmq, Redis, and Elixir on your machine. This demo assumes
# Rabbit and Redis are running on the default ports on localhost.
#
# From the project root, run `iex -S mix` to start the Elixir REPL with this
# code compiled. Start the server by invoking:
#
# {:ok, pid} = RedisRabbitElixir.start_link
#
# The GenServer is now running and pattern subscribed to our Redis instance.
#
# To send some sample events, enable keyevent notifications in Redis:
#
# $ redis-cli
# 127.0.0.1:6379> CONFIG SET notify-keyspace-events AE
# OK
# 127.0.0.1:6379> SET foo bar
# OK
#
# You see the following output in your iex session:
#
# Received PubSub message: foo
#
# And you should see the message in our Rabbit queue:
#
# $ sudo rabbitmqctl list_queues
# Listing queues ...
# rabbit_channel_foo 1
defmodule RedisRabbitElixir do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, :ok, name: :redis_pubsub_test)
end
def init(:ok) do
{:ok, %{pub_sub_conn: nil}, 0}
end
def handle_info(:timeout, _state) do
{:ok, client_sub} = Redix.PubSub.start_link
# Registering `self()` as the recipient will send published messages
# to the GenServer to be handled by `handle_info` for :message.
:ok = Redix.PubSub.psubscribe(client_sub, "__keyevent@*__:set", self())
{:noreply, %{pub_sub_conn: client_sub}}
end
def handle_info({:redix_pubsub, :psubscribe, _channel, _}, state) do
{:noreply, state}
end
def handle_info({:redix_pubsub, :pmessage, message, _channel}, state) do
IO.puts "Received PubSub message: #{message}"
send_key_to_rabbit(message)
{:noreply, state}
end
defp send_key_to_rabbit(key) do
# Spawns a new Elixir Process (not a system one) to send the key to Rabbit.
# The process will exit automatically once its work is done.
# This can probably be refactored into a different GenServer module to store
# connection state if we don't want to constantly be opening and closing
# connections to Rabbit.
spawn fn ->
{:ok, connection} = AMQP.Connection.open
{:ok, channel} = AMQP.Channel.open(connection)
AMQP.Queue.declare(channel, "rabbit_channel_foo")
AMQP.Basic.publish(channel, "", "rabbit_channel_foo", key)
AMQP.Connection.close(connection)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment