diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 14aaaa8bbc7..2da99393a02 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -288,8 +288,9 @@ class TopicQuery list .where("tu.last_read_post_number < topics.#{col_name}") - .where("COALESCE(tu.notification_level, :regular) >= :tracking", - regular: TopicUser.notification_levels[:regular], tracking: TopicUser.notification_levels[:tracking]) + .where("tu.notification_level >= :tracking", + tracking: TopicUser.notification_levels[:tracking] + ) end def prioritize_pinned_topics(topics, options) @@ -369,6 +370,10 @@ class TopicQuery result end + def unread_results_redis_key + "last_unread_result_bumped_at:#{@user.id}" + end + def unread_results(options = {}) result = TopicQuery.unread_filter( default_results(options.reverse_merge(unordered: true)), @@ -380,6 +385,17 @@ class TopicQuery result = filter_callback.call(:unread, result, @user, options) end + if !(last_bumped_at = $redis.get(unread_results_redis_key)) + last_bumped_at = result.unscope(:limit, :order).order(:bumped_at).first&.bumped_at + + $redis.setex( + unread_results_redis_key, + 1.hour.to_i, + (last_bumped_at || Time.zone.now).to_s + ) + end + + result = result.where("topics.bumped_at >= ?", last_bumped_at) if last_bumped_at suggested_ordering(result, options) end diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index add11d20666..ab682837745 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -443,6 +443,9 @@ describe TopicQuery do end context 'unread / read topics' do + after do + $redis.flushall + end context 'with no data' do it "has no unread topics" do @@ -484,10 +487,15 @@ describe TopicQuery do context 'list_unread' do it 'lists topics correctly' do - new_topic = Fabricate(:post, user: creator).topic + freeze_time do + new_topic = Fabricate(:post, user: creator).topic - expect(topic_query.list_unread.topics).to eq([]) - expect(topic_query.list_read.topics).to match_array([fully_read, partially_read]) + expect(topic_query.list_unread.topics).to eq([]) + expect(topic_query.list_read.topics).to match_array([fully_read, partially_read]) + + expect($redis.get(topic_query.unread_results_redis_key)) + .to eq(Time.zone.now.to_s) + end end end @@ -495,10 +503,16 @@ describe TopicQuery do before do user.user_option.auto_track_topics_after_msecs = 0 user.user_option.save + partially_read.update!(bumped_at: 2.days.ago) end it 'only contains the partially read topic' do - expect(topic_query.list_unread.topics).to eq([partially_read]) + freeze_time do + expect(topic_query.list_unread.topics).to eq([partially_read]) + + expect($redis.get(topic_query.unread_results_redis_key)) + .to eq(partially_read.bumped_at.to_s) + end end end