lud

lud

Catching NO_ROUTE from AMQP.Basic.publish

Hi everyone!

I wrote a unit test where I want to ensure that the app is able to connect to RabbitMQ (using Broadway), so the test will start Broadway, then publish to some exchange, and expect a message from the Broadway processor.

The problem is that it takes time for the Broadway producer to declare the exchange and bind the queue, so in my test when I publish the message it is not routed.

My current solution is to add a small sleep but it is not reliable (and slows down tests).

{:ok, rmq_consumer} = consumer_mod.start_link(job_handler: job_handler, start_mode: :normal)

# Generate a random string to validate that we receive this specific
# message.

randstr = Ecto.UUID.generate()
payload = Jason.encode!(%{"randstr" => randstr})

# Connect to RMQ and deliver the payload to the configured exchange.
# Currently I have not figured a way to ensure that the queue was declared
# and to republish otherwise, so we sleep for one second.

config = consumer_mod.config()
{:ok, conn} = AMQP.Connection.open(config.connection)
{:ok, chan} = AMQP.Channel.open(conn)
Process.sleep(1000)
:ok = ensure_routed_publish(chan, config.exchange, "", payload)

# We should receive the same random string from our test handler

assert_receive {:rmq_str, ^randstr}, 1000

I tried to fiddle with AMQP.Confirm.select, the :mandatory option, the wait_confirm_or_die function, but it does not work. Everytime AMQP will happily tell me that everything is fine though my message will never be routed as with select I can see the error in the logs.

How can I write the ensure_routed_publish/4 function so it returns {:error, _} when the message is not routed so I can retry it and avoid the sleeping?

Thank you.

Marked As Solved

BradS2S

BradS2S

You can use return to register a handler to deal with returned messages.

If you get this message: {:basic_return, payload, meta}, send it again.

https://hexdocs.pm/amqp/AMQP.Basic.html#return/2

Also Liked

lud

lud

Yes this is more or less what I did:

  defp ensure_routed_publish(chan, exchange, key, payload) do
    AMQP.Confirm.select(chan)
    AMQP.Confirm.register_handler(chan, self())
    AMQP.Basic.return(chan, self())
    publish_loop(chan, exchange, key, payload)
  end

  defp publish_loop(chan, exchange, key, payload) do
    :ok = AMQP.Basic.publish(chan, exchange, key, payload, mandatory: true)

    receive do
      {:basic_return, _, %{reply_text: "NO_ROUTE"}} ->
        receive do
          {:basic_ack, _, _} ->
            Process.sleep(50)
            publish_loop(chan, exchange, key, payload)
        end

      {:basic_ack, _, _} ->
        :ok
    after
      5000 -> flunk("could not deliver message to RabbitMQ")
    end
  end

(It is in a test so we know the queue will exist at some point.)

Where Next?

Popular in Questions Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
LegitStack
I’m hoping you guys can give me some general advice and perhaps code examples if you’re feeling up to it. I’m very interested in Elixir,...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
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
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

We're in Beta

About us Mission Statement