lud
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.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 5- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
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.
lud
Hi, thank you.
Unfortunately this does not work because I receive a message only in case there was an error. So when everything goes right i’ll have to add a timeout to the
receive, which is only slightly better than thesleep.Edit: It seems that if I also add the following:
the
:basic_ackmessage is always delivered after the:basic_returnmessage, so it may be safe to consider that receiving basic_ack without basic_return means that the message was routed.BradS2S
Would something like this work?
Def ensure_routed_publish(chan, exchange, routing_key, payload) do
AMQP.Basic.return(chan, self())
AMQP.Confirm.select(chan)
AMQP.Confirm.register_handler(chan, self())
:ok = AMQP.Basic.publish(chan, exchange, routing_key, payload, mandatory: true)
receive do
{:basic_ack, _, _} →
:ok
{:basic_return, returned_payload, _} →
{:error, returned_payload}
after
timeout →
{:error, :timeout}
end
end
lud
Yes this is more or less what I did:
(It is in a test so we know the queue will exist at some point.)
lud
Hi!
Do you know if there is a way to catch when an exchange does not exist?
I have the following code:
And was expecting to receive a basic nack.
I also have this code
AMQP.Basic.return(chan, self())but it does not seem to handle that.Thank you!