unread_data: Ensure deterministic ordering of unread message rows.

Earlier, in `get_raw_unread_data` the ordering was applied inside
the CTE.

Once we leave the CTE scope and do a join, SQL makes no promise
about preserving the row order unless we re-specify ORDER BY in
the outer query.

Since, there was no ORDER BY clause in the outer query it was
resulting in a random ordering of the entries. This bug was caught
by `test_unreads_case_insensitive_topics` failing in a flaky way.

This commit fixes the bug.

(cherry picked from commit ccc82976dc)
This commit is contained in:
Prakhar Pratyush
2025-04-22 14:13:23 +05:30
committed by Tim Abbott
parent 7ee999917f
commit 859cc29657

View File

@@ -857,6 +857,7 @@ def get_raw_unread_data(
"flags",
"recipient_id",
)
# Descending order, so truncation keeps the latest unreads.
.order_by("-message_id")
)
@@ -909,9 +910,13 @@ def get_raw_unread_data(
"recipient__type",
"recipient__type_id",
)
# Output in ascending order. We can't just reverse,
# since the CTE join does not guarantee that it
# preserves the original descending order.
.order_by("message_id")
)
rows = list(reversed(user_msgs))
rows = list(user_msgs)
finally:
cursor.execute("SET enable_bitmapscan TO on")
return extract_unread_data_from_um_rows(rows, user_profile)