Merge pull request #3288 from vitorpamplona/claude/determined-ritchie-g281jh

Fix unstable sort in live activity feeds by snapshotting status order
This commit is contained in:
Vitor Pamplona
2026-06-19 17:27:08 -04:00
committed by GitHub
2 changed files with 16 additions and 2 deletions
@@ -106,10 +106,17 @@ open class DiscoverLiveFeedFilter(
val allParticipants =
items.associate { it to counter.countFollowsThatParticipateOn(it, null) }
// Snapshots the status order once per item. convertStatusToOrder reads the
// OnlineChecker cache and the moving five-minute window, both of which can change
// mid-sort (a background online check can update the cache). Reading it lazily inside
// the comparator makes the ordering unstable and TimSort throws
// "Comparison method violates its general contract!".
val statusOrders = items.associateWith { convertStatusToOrder(it.event) }
return items
.sortedWith(
compareBy(
{ convertStatusToOrder(it.event) },
{ statusOrders[it] },
{ participantCounts[it] },
{ allParticipants[it] },
{
@@ -106,10 +106,17 @@ class LiveStreamsFeedFilter(
val allParticipants =
items.associate { it to counter.countFollowsThatParticipateOn(it, null) }
// Snapshots the status order once per item. convertStatusToOrder reads the
// OnlineChecker cache and the moving five-minute window, both of which can change
// mid-sort (a background online check can update the cache). Reading it lazily inside
// the comparator makes the ordering unstable and TimSort throws
// "Comparison method violates its general contract!".
val statusOrders = items.associateWith { convertStatusToOrder(it.event) }
return items
.sortedWith(
compareBy(
{ convertStatusToOrder(it.event) },
{ statusOrders[it] },
{ participantCounts[it] },
{ allParticipants[it] },
{