From 394cebce57434c1128d0ca9b4f6bc20da891652a Mon Sep 17 00:00:00 2001 From: noellabo Date: Wed, 22 Sep 2021 13:56:05 +0900 Subject: [PATCH] Fix emoji reaction events to be notified according to visibility --- app/lib/feed_manager.rb | 7 +++- app/models/emoji_reaction.rb | 2 +- app/workers/concerns/publish_scope.rb | 41 ++++++++++++++++++++ app/workers/publish_emoji_reaction_worker.rb | 26 ++++++++----- 4 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 app/workers/concerns/publish_scope.rb diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb index 1f0057a86..8273129f0 100644 --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@ -14,11 +14,16 @@ class FeedManager # or the tracking sets will grow forever REBLOG_FALLOFF = 40 + # Get active account + def active_accounts + Account.joins(:user).where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago) + end + # Execute block for every active account # @yield [Account] # @return [void] def with_active_accounts(&block) - Account.joins(:user).where('users.current_sign_in_at > ?', User::ACTIVE_DURATION.ago).find_each(&block) + active_accounts.find_each(&block) end # Redis key of a feed diff --git a/app/models/emoji_reaction.rb b/app/models/emoji_reaction.rb index 11c3acae9..869c8cc98 100644 --- a/app/models/emoji_reaction.rb +++ b/app/models/emoji_reaction.rb @@ -40,7 +40,7 @@ class EmojiReaction < ApplicationRecord private def queue_publish - PublishEmojiReactionWorker.perform_async(status_id, name) unless status.destroyed? + PublishEmojiReactionWorker.perform_async(status_id, account_id, name) unless status.destroyed? end def refresh_status diff --git a/app/workers/concerns/publish_scope.rb b/app/workers/concerns/publish_scope.rb new file mode 100644 index 000000000..c8da8e01c --- /dev/null +++ b/app/workers/concerns/publish_scope.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module PublishScope + extend ActiveSupport::Concern + + included do + def visibility_scope + case @status.visibility + when 'public', 'unlisted' + local_scope + when 'private' + Account.where(id: Account + .union(local_followers_scope) + .union(local_mentions_scope) + .union(local_sender_scope) + ) + when 'limited', 'direct' + Account.where(id: Account + .union(local_mentions_scope) + .union(local_sender_scope) + ) + end.select(:id) + end + + def local_scope + Account.local + end + + def local_followers_scope + @status.account.delivery_followers.local.select(:id) + end + + def local_mentions_scope + Account.local.where(id: @status.mentions.select(:account_id)).select(:id) + end + + def local_sender_scope + Account.local.where(id: @account_id).select(:id) + end + end +end diff --git a/app/workers/publish_emoji_reaction_worker.rb b/app/workers/publish_emoji_reaction_worker.rb index 37d9f4e92..c1f9ca2dc 100644 --- a/app/workers/publish_emoji_reaction_worker.rb +++ b/app/workers/publish_emoji_reaction_worker.rb @@ -4,20 +4,26 @@ class PublishEmojiReactionWorker include Sidekiq::Worker include Redisable include RoutingHelper + include PublishScope - def perform(status_id, name) - status = Status.find(status_id) - payload = status.grouped_emoji_reactions.find { |emoji_reaction| emoji_reaction['name'] == name } - payload ||= { name: name, count: 0, account_ids: [] } + def perform(status_id, account_id, name) + @status = Status.find(status_id) + @account_id = account_id + @name = name - payload['status_id'] = status_id.to_s - - json = Oj.dump(event: :'emoji_reaction', payload: payload) - - FeedManager.instance.with_active_accounts do |account| - redis.publish("timeline:#{account.id}", json) if redis.exists?("subscribed:timeline:#{account.id}") + FeedManager.instance.active_accounts.merge(visibility_scope).find_each do |account| + redis.publish("timeline:#{account.id}", payload_json) if redis.exists?("subscribed:timeline:#{account.id}") end rescue ActiveRecord::RecordNotFound true end + + def payload_json + payload = @status.grouped_emoji_reactions.find { |emoji_reaction| emoji_reaction['name'] == @name } + payload ||= { name: @name, count: 0, account_ids: [] } + + payload['status_id'] = @status.id.to_s + + Oj.dump(event: :'emoji_reaction', payload: payload) + end end