Per Message TTL Caveats Documentation Update #1789
Replies: 8 comments 3 replies
-
This is still just as true for many common cases. The rest of the section tries to get
The current copywriting lumps together the cases when there is a DLX and when there isn't one (message TTL is often used as a way to control queue overflow, not for scheduling via DLX). |
Beta Was this translation helpful? Give feedback.
-
But in my code example that's not the case, the queue already had an unconsumed message at the head and published messages with ttl when they got expired they were dead-lettered despite having a message with no expiration at the head of the queue. Doesn't that contradict with the documentation? |
Beta Was this translation helpful? Give feedback.
-
@ramikhafagi96 I have updated my comment above. You are making an assumption that everyone uses TTL for scheduled dead lettering. That's not at all the case. |
Beta Was this translation helpful? Give feedback.
-
There are several different scenarios that can have certain differences:
The current wording is correct for 1 and 2, you won't observe data deletion before messages reach the head. Your example does not mention whether the classic queue used is a CQv2 queue or a CQv1 one. There may be subtle differences. As for 5, expired messages won't be deleted until they reach the head of the queue but the dead lettering happens concurrently to that. My guess is that when concurrent DLX was introduced to quorum queues, it was extended to CQs. |
Beta Was this translation helpful? Give feedback.
-
A quick search suggests that for QQs, the dead lettering process is indeed concurrent:
However, that still does not mean that messages are marked for deletion immediately when they expire, However, for classic queues things are much more involved and I am not convinced after a few minutes of digging in that your observations are universally true (they may be in your specific example, that I am not questioning). Specifically, %% optimisation: it would be perfectly safe to always
%% invoke drop_expired_msgs here, but that is expensive so
%% we only do that if a new message that might have an
%% expiry ends up at the head of the queue. If the head
%% remains unchanged, or if the newly published message
%% has no expiry and becomes the head of the queue then
%% the call is unnecessary.
case {Dropped, QLen =:= 1, Props#message_properties.expiry} of
{false, false, _} -> State3;
{true, true, undefined} -> State3;
{_, _, _} -> drop_expired_msgs(State3)
end In other words, classic queues in Which means that for the sake of documentation, we can safely say that expired messages are A single Python script won't provide an answer because you must have different load patterns I will push some TTL guide doc updates that at least demonstrate the difference between the non-DLX and DLX cases (they simply should have separate doc sections), and that different queue types |
Beta Was this translation helpful? Give feedback.
-
@ramikhafagi96 while not directly related, note that your example
So while your findings is a good reminder that we need to re-organize the TTL guide, I am not convinced that every classic queue user will always observe the same behavior, for a number of unrelated and less-than-obvious reasons listed in this discussion. So we cannot make the docs say what you want them to say, not without a much more nuanced description after clarifying the current CQ behavior with the team members who have worked on CQv2 as well as message TTL support in QQs. |
Beta Was this translation helpful? Give feedback.
-
a709816 introduces some initial edits that are badly needed. The QQ and CQ sections can be clarified later. At the very least we no longer lump together like five different cases that really should be explained separately. Thank you for bringing this up, @ramikhafagi96 👍 |
Beta Was this translation helpful? Give feedback.
-
After discussing it with two more team members, we will largely revert to the previous claim because QQs do not do concurrent dead lettering per se (that would make the FIFO guarantees highly dubious) but with just three messages in a queue and expiration in the range of [0; 10] seconds it is easy to arrive to the wrong conclusions. The docs were not organized very well but they were factually correct. |
Beta Was this translation helpful? Give feedback.
-
Is your feature request related to a problem? Please describe.
Problem Definition
In Time-To-Live and Expiration Caveats Section, It is mentioned that
Only when expired messages reach the head of a queue will they actually be discarded (or dead-lettered).
which is not true now. What actually happens is when the message TTL expires it gets discarded and dead-lettered even if it was not at the head of the queue. So, I think this was an old behavior given that it was written 6 years ago and it hasn't been updated since then.Impact
Because of this out-dated documentation we took a design choice to implement delayed messages by creating many queues with different TTL on the queue itself and it made our design very complicated while it could've been much simpler if we used TTL on messages
Code Example
You can find below code example for showing that the mentioned behavior is not valid. The code example creates two queues the first one messages with expiration property are enqueued in it and when the TTL expires it gets dead-lettered to another queue and there's a running consumer that consumes from the dead-letter queue.
Describe the solution you'd like
I suggest that this should be updated because it can lead to bad design choices
Describe alternatives you've considered
No response
Additional context
No response
Beta Was this translation helpful? Give feedback.
All reactions