-
Notifications
You must be signed in to change notification settings - Fork 476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
question about dead exchange letter | x-death #494
Comments
Hi @fas3r, One of the limitations of the amqp protocol is that it doesn't provide a way to check the number of times a message has been redelivered / republished. As far as I can tell you only two options are
Things you might consider for option 1...
I maintain a wrapper for amqplib which also handles delayed retries in a similar way to what you describe. It's worth checking out if only to give you some more ideas. |
Hello @cressie176 , First, thanks for your message.
That's exactly what I was thinking of, as the Regarding option 2 I did not know that we can expect an id to be return from the producer, I will check that out. Also thanks for the link to the wrapper, while readingI guess you are referring to this in the readme ?
I did not know about rascal ... I did the Fn for the mapping configuration/logic by myself ... :/ I will check that for sure. Thanks |
The producer has to set the id. There is a field for it, but there's no guarantee the id is set. Rascal will default the id to a UUID if one isn't already specified.
No, that's talking about confirm channels - nothing to do with message ids. |
Yep, you are right, I just check the field reference, I was mistaken with the correlation-id which have a completely different purpose. On my side it's not as extended as you, I add case by case and I can declare classical queues/exchanges via the mapping but I don't expect to use that part much. So far I do only 2 case:
The "wait and delete" is very similar than the "retries x times" case as it's also using the dead letter + routing key, it just hold msg in a queue with the appropriate TTL. Afterwards, it goes back to the original queue . As the msg is marked as republished it get consume and delete stuff in cache/db. Regarding
I recall that from the doc. What do you do ? Between each consumer you check and update the "tracking list" ? The problem is what to do if the msg is delivered but you don't get "success" and vice versa. I will definitively look at your code, like how you manage the number of channels/connections, repeat the msg if this one fails. I also see that you are using the correlation-id, I need to add it. Thanks |
There are two scenarios I'm concerned with.
For the first scenario I favour the delayed retry mechanism by forwarding a copy of the message + some tracking headers in a manner similar to what we've been discussing. If the number of attempts exceeds some threshold I permanently dead letter, and take manual intervention. For the second scenario I track message ids of redelivered messages in redis, with an auto-expiry. If the attempts exceed a threshold I permanently dead letter. Because I only do this for redelivered messages it doesn't affect normal performance. Both approaches require the consumer to tolerate duplicate messages. |
Hello @cressie176 , I think for point number 1 and 2 I will wait to have more concrete test throw the app to look at it, but It will be very similar approach than you i guess. Thanks again for all your detailed answers. fas3r. |
Welcome. Please close the issue if there's no further discussion needed. |
Hello,
I'm testing rabbitmq and I came up with something like that in order to use the dead queue letter / dead exchange + routing key.
The image below represent the flow used by the Queues/Exchanges...
The message arrives in the
GQL-expire-agents
Queue on the left and is consume by the_sendMsgToRetry
function that rewrite the msg and send it to the Dead exchange with the routing key.After been hold in the queue, the message goes to the
QLX-retry-expire-agents
and goes to theGQL-expire-agents
queue and been consume by_sendMsgToRetry
... etc, etc until it reach the maximum of retries.In the details it would be like this :
msg_arrive --> GQL-expire-agents --> _sendMsgToRetry --> fnOnRetry --> dead exchanger --> routing --> queue holding msg ( TQL-expire...1,2 and 3) --> QLX fanout exchange --> GQL-expire-agents --> _sendMsgToRetry --> fnOnRe.... .... fnOnTerminate
where :
_sendMsgToRetry
: is the function to reformat the msg and publish the message to the exchangerfnOnRetry
: the function inside _sendMsgToRetry representing the consumer to use while retryingfnOnTerminate
: the function inside _sendMsgToRetry representing the consumer to use after max attempt.I bind the function consumer
_sendMsgToRetry
to the queue GQL-expire-agents on the picture. It's the queue are created.Here is the function that I use to check the number of attempt, reformat the message and republish to the Dead Exchanger with the appropriate routing key. It's where the consumer
fnOnRetry
andfnOnTerminate
.I put in place test that send ~100K msg/minutes and it seems to do the job with 3 nodes in cluster. In really I don't expect to receive that amount ... far from that ... as a final usage it's just to have some kind of persistent scheduler/countdown.
We looked into other product or modules in JS using redis but at the end, we just need to have a persistent separate service that is able to repeat on definite period some actions (1 minute to 3days for the worst case) .
My question are the following, in term of code, what should I do to not use a custom "check" in the content of the message.
I read about
x-death
but I did not manage to access/set/read it ... if you have any idea because from what I read in the api documentation I should be able to set 'x-death' from_sendMsgToRetry
, no ?Please mind the
Promise.resolve()
and theconcat.(....
.. in the code.Thanks by advance.
Fas3r
The text was updated successfully, but these errors were encountered: