manhtranlinh

manhtranlinh

RPC with Broadway and RabbitMQ, the caller can auto start the receiver

Hi everyone,
I implemented the example from this blog RPC over RabbitMQ (with Elixir) – Andrea Leopardi.
My dev environment:
Elixir 1.14.2, RabbitMQ 3.12.0, Erlang 25.3.2.2, {:amqp, "~> 3.3"}, {:broadway, "~> 1.0"}, {:broadway_rabbitmq, "~> 0.7.0"}
I created: a caller module, a receiver module use Broadway and can start with Supervisor.
The situation is: if I did not start the receiver module, but run the caller program I still get the result as the receiver is started.
I don’t know if whether it is wrong with my dev environment or it is the auto start mechanism of Broadway, RabbitMQ and Supervisor.
If someone face this situation, please help to explain to me.

  1. caller_rpc_service.exs
defmodule CallerRPCService do
  def wait_for_messages(_channel, correlation_id) do
    receive do
      {:basic_deliver, payload, %{correlation_id: ^correlation_id}} ->
        IO.puts("Response Message:  #{inspect(payload)}")
    end
  end
end

{:ok, connection} = AMQP.Connection.open()
{:ok, channel} = AMQP.Channel.open(connection)

{:ok, %{queue: queue_name}} = AMQP.Queue.declare(channel, "", exclusive: true)

AMQP.Basic.consume(channel, queue_name, nil)

{headers, message} = {[{"destination", "my_service"}], "Hello Broadway and RPC."}
correlation_id = :erlang.unique_integer() |> :erlang.integer_to_binary() |> Base.encode64()

AMQP.Exchange.declare(channel, "rpc", :headers,
  arguments: [{"destination", :longstr, "my_service"}]
)

AMQP.Basic.publish(channel, "rpc", "", message,
  reply_to: queue_name,
  correlation_id: correlation_id,
  headers: headers
)
CallerRPCService.wait_for_messages(channel, correlation_id)

  1. receiver_rpc_service.ex
defmodule MyService.RPCConsumer do
  use Broadway

  @producer BroadwayRabbitMQ.Producer

  @producer_config [
    queue: "my_service.rpcs",
    declare: [durable: true],
    bindings: [
      {"rpc", arguments: [{"destination", :longstr, "my_service"}]}
    ],
    metadata: [:reply_to, :correlation_id],
    on_failure: :reject_and_requeue # mandatory option 
  ]
  def start_link(_args) do
    options = [
      name: RPCConsumerPipeline,
      producer: [
        module: {@producer, @producer_config}
      ],
      processors: [
        default: []
      ]
    ]

    Broadway.start_link(__MODULE__, options)
  end

  def handle_message(_, %Broadway.Message{} = message, _context) do
    IO.puts("Request message: #{inspect(message)}")

    AMQP.Basic.publish(
      message.metadata.amqp_channel,
      "",
      message.metadata.reply_to,
      "We have got it. Ok!",
      correlation_id: message.metadata.correlation_id
    )

    message
  end
end

  1. application.ex
defmodule RabbimqTutorials.Application do
  @moduledoc false 
 alias MyService.RPCConsumer

  use Application
  @impl true
  def start(_type, _args) do
    children = [
      RPCConsumer
    ]
    opts = [strategy: :one_for_one, name: RabbimqTutorials.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Where Next?

Popular in Questions Top

fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement