mirror of
https://github.com/discourse/discourse.git
synced 2025-01-30 04:19:28 +08:00
FIX: Ensure directory items appear in a consistent order (#11370)
User directory items are sorted by some activity metric. If those metrics have the same value, postgres does not guarantee the order in which they will be returned. This can cause issues in pagination - some users may appear twice, and some may be missed. To illustrate ``` pry(main)> query = DirectoryItem.where(period_type: DirectoryItem.period_types[:weekly]).order(:likes_received).limit(50); pry(main)> page1 = query.offset(0).pluck(:id); pry(main)> page2 = query.offset(50).pluck(:id); pry(main)> (page1 & page2).count # users on both pages => 29 ``` If we use the primary key to tie-break matching metrics, things are much more reliable ``` pry(main)> query = DirectoryItem.where(period_type: DirectoryItem.period_types[:weekly]).order(:likes_received, :id).limit(50); pry(main)> page1 = query.offset(0).pluck(:id); pry(main)> page2 = query.offset(50).pluck(:id); pry(main)> (page1 & page2).count # users on both pages => 0 ``` This most commonly effects new sites where all the directory metrics are zero. The fact that the ordering is indeterminate makes it difficult to write a reliable test case for this.
This commit is contained in:
parent
65eec147fc
commit
e7bad9f05d
|
@ -29,9 +29,9 @@ class DirectoryItemsController < ApplicationController
|
|||
order = params[:order] || DirectoryItem.headings.first
|
||||
dir = params[:asc] ? 'ASC' : 'DESC'
|
||||
if DirectoryItem.headings.include?(order.to_sym)
|
||||
result = result.order("directory_items.#{order} #{dir}")
|
||||
result = result.order("directory_items.#{order} #{dir}, directory_items.id")
|
||||
elsif params[:order] === 'username'
|
||||
result = result.order("users.#{order} #{dir}")
|
||||
result = result.order("users.#{order} #{dir}, directory_items.id")
|
||||
end
|
||||
|
||||
if period_type == DirectoryItem.period_types[:all]
|
||||
|
|
Loading…
Reference in New Issue
Block a user