diff --git a/README.md b/README.md index ee6b520..7674630 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ end * when a client checks out a channel out of the pool the connection worker monitors that client to return the channel into it in case of a crash -* in case you don't want to pool channels, you can disable this feature +* in case you don't want to pool channels, you can disable this feature by setting the `channels` number to 0, then you can create channels on demand ## High Level Architecture @@ -58,6 +58,24 @@ Also: * Monitor clients accessing channels, * Queue and dequeue channels from the pool in order to make them accessible to one client at a time reducing the potential for race conditions. +## Setup RabbitMQ with docker + +```bash +# pull RabbitMQ image from docker +$> docker pull rabbitmq:3.7.7-management +# run docker in background +# name the container +# remove container if already exists +# attach default port between the container and your laptop +# attach default management port between the container and your laptop +# start rabbitmq with management console +$> docker run --detach --rm --hostname bugs-bunny --name roger_rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.7.7-management +# if you need to stop the container +$> docker stop roger_rabbit +# if you need to remove the container manually +$> docker container rm roger_rabbit +``` + ## Supervision hierarchy ![supervisor diagram](https://user-images.githubusercontent.com/1157892/52127565-681b8400-2600-11e9-8c37-34287e4c9b2c.png) @@ -118,7 +136,7 @@ queue no longer exist). Images are taken from [RabbitMQ Tutorials](https://www.rabbitmq.com/tutorials/tutorial-four-python.html) -### Setting up a direct exchange with bindings +## Setting up a direct exchange with bindings ![Direct Exchange Multiple](https://www.rabbitmq.com/img/tutorials/direct-exchange.png) @@ -164,7 +182,7 @@ ExRabbitPool.PoolSupervisor.start_link( ExRabbitPool.Worker.SetupQueue.start_link({pool_id, queues_config}) ``` -### Setting up a direct exchange with multiple bindings +## Setting up a direct exchange with multiple bindings ![Direct Exchange Multiple](https://www.rabbitmq.com/img/tutorials/direct-exchange-multiple.png) @@ -202,3 +220,46 @@ ExRabbitPool.PoolSupervisor.start_link( ExRabbitPool.Worker.SetupQueue.start_link({pool_id, queues_config}) ``` + +## EchoConsumer - Example + +In the `examples` directory you are going to find an implementation of a RabbitMQ +consumer using the library, all you need to do is, starting RabbitMQ +[with docker](#setup-rabbitmq-with-docker), and copy/paste the following code into the `iex` console. +What it does is, setup the connection pool, setup the queues, exchanges and +bindings to use, start the consumer and finally publish some messages to the +exchange so the consumer can echo it. + +```elixir +rabbitmq_config = [channels: 2] + +rabbitmq_conn_pool = [ + name: {:local, :connection_pool}, + worker_module: ExRabbitPool.Worker.RabbitConnection, + size: 1, + max_overflow: 0 +] + +{:ok, pid} = + ExRabbitPool.PoolSupervisor.start_link( + rabbitmq_config: rabbitmq_config, + connection_pools: [rabbitmq_conn_pool] + ) + +queue = "ex_rabbit_pool" +exchange = "my_exchange" +routing_key = "example" + +ExRabbitPool.with_channel(:connection_pool, fn {:ok, channel} -> + {:ok, _} = AMQP.Queue.declare(channel, queue, auto_delete: true, exclusive: true) + :ok = AMQP.Exchange.declare(channel, exchange, :direct, auto_delete: true, exclusive: true) + :ok = AMQP.Queue.bind(channel, queue, exchange, routing_key: routing_key) +end) + +{:ok, consumer_pid} = Example.EchoConsumer.start_link(pool_id: :connection_pool, queue: queue) + +ExRabbitPool.with_channel(:connection_pool, fn {:ok, channel} -> + :ok = AMQP.Basic.publish(channel, exchange, routing_key, "Hello World!") + :ok = AMQP.Basic.publish(channel, exchange, routing_key, "Hell Yeah!") +end) +``` diff --git a/examples/echo_consumer.ex b/examples/echo_consumer.ex index a29edcc..df74301 100644 --- a/examples/echo_consumer.ex +++ b/examples/echo_consumer.ex @@ -34,35 +34,3 @@ defmodule Example.EchoConsumer do :ok end end - -rabbitmq_config = [channels: 2] - -rabbitmq_conn_pool = [ - name: {:local, :connection_pool}, - worker_module: ExRabbitPool.Worker.RabbitConnection, - size: 1, - max_overflow: 0 -] - -{:ok, pid} = - ExRabbitPool.PoolSupervisor.start_link( - rabbitmq_config: rabbitmq_config, - rabbitmq_conn_pool: rabbitmq_conn_pool - ) - -queue = "ex_rabbit_pool" -exchange = "my_exchange" -routing_key = "example" - -ExRabbitPool.with_channel(:connection_pool, fn {:ok, channel} -> - {:ok, _} = AMQP.Queue.declare(channel, queue, auto_delete: true, exclusive: true) - :ok = AMQP.Exchange.declare(channel, exchange, :direct, auto_delete: true, exclusive: true) - :ok = AMQP.Queue.bind(channel, queue, exchange, routing_key: routing_key) -end) - -{:ok, consumer_pid} = Example.EchoConsumer.start_link(pool_id: :connection_pool, queue: queue) - -ExRabbitPool.with_channel(:connection_pool, fn {:ok, channel} -> - :ok = AMQP.Basic.publish(channel, exchange, routing_key, "Hello World!") - :ok = AMQP.Basic.publish(channel, exchange, routing_key, "Hell Yeah!") -end)