DEV: Add backend support for unread and new topics list (#20293)

This commit adds backend support for a new topics list that combines both the current unread and new topics lists. We're going to experiment with this new list (name TBD) internally and decide if this feature is something that we want to fully build.

Internal topic: t/77234.
This commit is contained in:
Osama Sayegh
2023-02-16 16:02:09 +03:00
committed by GitHub
parent c541bd05a8
commit 5423e7c5b7
2 changed files with 184 additions and 15 deletions

View File

@ -507,21 +507,7 @@ class TopicQuery
whisperer: @user&.whisperer?,
).order("CASE WHEN topics.user_id = tu.user_id THEN 1 ELSE 2 END")
if @user
# micro optimisation so we don't load up all of user stats which we do not need
unread_at =
DB.query_single("select first_unread_at from user_stats where user_id = ?", @user.id).first
if max_age = options[:max_age]
max_age_date = max_age.days.ago
unread_at ||= max_age_date
unread_at = unread_at > max_age_date ? unread_at : max_age_date
end
# perf note, in the past we tried doing this in a subquery but performance was
# terrible, also tried with a join and it was bad
result = result.where("topics.updated_at >= ?", unread_at)
end
result = apply_max_age_limit(result, options)
self.class.results_filter_callbacks.each do |filter_callback|
result = filter_callback.call(:unread, result, @user, options)
@ -548,6 +534,28 @@ class TopicQuery
suggested_ordering(result, options)
end
def new_and_unread_results(options = {})
base = default_results(options.reverse_merge(unordered: true))
new_results =
TopicQuery.new_filter(
base,
treat_as_new_topic_start_date: @user.user_option.treat_as_new_topic_start_date,
)
new_results = remove_muted(new_results, @user, options)
new_results = remove_dismissed(new_results, @user)
unread_results =
apply_max_age_limit(TopicQuery.unread_filter(base, whisperer: @user&.whisperer?), options)
base.joins_values.concat(new_results.joins_values, unread_results.joins_values)
base.joins_values.uniq!
results = base.merge(new_results.or(unread_results))
results = results.order("CASE WHEN topics.user_id = tu.user_id THEN 1 ELSE 2 END")
suggested_ordering(results, options)
end
protected
def per_page_setting
@ -1167,4 +1175,23 @@ class TopicQuery
col_name = whisperer ? "highest_staff_post_number" : "highest_post_number"
list.where("tu.last_read_post_number IS NULL OR tu.last_read_post_number < topics.#{col_name}")
end
def apply_max_age_limit(results, options)
if @user
# micro optimisation so we don't load up all of user stats which we do not need
unread_at =
DB.query_single("select first_unread_at from user_stats where user_id = ?", @user.id).first
if max_age = options[:max_age]
max_age_date = max_age.days.ago
unread_at ||= max_age_date
unread_at = unread_at > max_age_date ? unread_at : max_age_date
end
# perf note, in the past we tried doing this in a subquery but performance was
# terrible, also tried with a join and it was bad
results = results.where("topics.updated_at >= ?", unread_at)
end
results
end
end