forked from cybrespace/mastodon
		
	Spawn FeedInsertWorker to deliver status into personal feed
This commit is contained in:
		
							parent
							
								
									5f54981846
								
							
						
					
					
						commit
						6fd865c000
					
				
					 5 changed files with 39 additions and 25 deletions
				
			
		| 
						 | 
					@ -11,11 +11,11 @@ class FeedManager
 | 
				
			||||||
    "feed:#{type}:#{id}"
 | 
					    "feed:#{type}:#{id}"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def filter?(timeline_type, status, receiver)
 | 
					  def filter?(timeline_type, status, receiver_id)
 | 
				
			||||||
    if timeline_type == :home
 | 
					    if timeline_type == :home
 | 
				
			||||||
      filter_from_home?(status, receiver)
 | 
					      filter_from_home?(status, receiver_id)
 | 
				
			||||||
    elsif timeline_type == :mentions
 | 
					    elsif timeline_type == :mentions
 | 
				
			||||||
      filter_from_mentions?(status, receiver)
 | 
					      filter_from_mentions?(status, receiver_id)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      false
 | 
					      false
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -91,39 +91,39 @@ class FeedManager
 | 
				
			||||||
    Redis.current
 | 
					    Redis.current
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def filter_from_home?(status, receiver)
 | 
					  def filter_from_home?(status, receiver_id)
 | 
				
			||||||
    return true if status.reply? && status.in_reply_to_id.nil?
 | 
					    return true if status.reply? && status.in_reply_to_id.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    check_for_mutes = [status.account_id]
 | 
					    check_for_mutes = [status.account_id]
 | 
				
			||||||
    check_for_mutes.concat([status.reblog.account_id]) if status.reblog?
 | 
					    check_for_mutes.concat([status.reblog.account_id]) if status.reblog?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true if receiver.muting?(check_for_mutes)
 | 
					    return true if Mute.where(account_id: receiver_id, target_account_id: check_for_mutes).any?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    check_for_blocks = status.mentions.map(&:account_id)
 | 
					    check_for_blocks = status.mentions.map(&:account_id)
 | 
				
			||||||
    check_for_blocks.concat([status.reblog.account_id]) if status.reblog?
 | 
					    check_for_blocks.concat([status.reblog.account_id]) if status.reblog?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true if receiver.blocking?(check_for_blocks)
 | 
					    return true if Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if status.reply? && !status.in_reply_to_account_id.nil?                                                              # Filter out if it's a reply
 | 
					    if status.reply? && !status.in_reply_to_account_id.nil?                                                              # Filter out if it's a reply
 | 
				
			||||||
      should_filter   = !receiver.following?(status.in_reply_to_account)      # and I'm not following the person it's a reply to
 | 
					      should_filter   = !Follow.where(account_id: receiver_id, target_account_id: status.in_reply_to_account_id).exists? # and I'm not following the person it's a reply to
 | 
				
			||||||
      should_filter &&= !(receiver.id == status.in_reply_to_account_id)       # and it's not a reply to me
 | 
					      should_filter &&= !(receiver_id == status.in_reply_to_account_id)                                                  # and it's not a reply to me
 | 
				
			||||||
      should_filter &&= !(status.account_id == status.in_reply_to_account_id)                                            # and it's not a self-reply
 | 
					      should_filter &&= !(status.account_id == status.in_reply_to_account_id)                                            # and it's not a self-reply
 | 
				
			||||||
      return should_filter
 | 
					      return should_filter
 | 
				
			||||||
    elsif status.reblog?                                                                                                 # Filter out a reblog
 | 
					    elsif status.reblog?                                                                                                 # Filter out a reblog
 | 
				
			||||||
      return status.reblog.account.blocking?(receiver)                        # or if the author of the reblogged status is blocking me
 | 
					      return Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists?                   # or if the author of the reblogged status is blocking me
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    false
 | 
					    false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def filter_from_mentions?(status, receiver)
 | 
					  def filter_from_mentions?(status, receiver_id)
 | 
				
			||||||
    check_for_blocks = [status.account_id]
 | 
					    check_for_blocks = [status.account_id]
 | 
				
			||||||
    check_for_blocks.concat(status.mentions.select('account_id').map(&:account_id))
 | 
					    check_for_blocks.concat(status.mentions.select('account_id').map(&:account_id))
 | 
				
			||||||
    check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
 | 
					    check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    should_filter   = receiver.id == status.account_id                                      # Filter if I'm mentioning myself
 | 
					    should_filter   = receiver_id == status.account_id                                                                                   # Filter if I'm mentioning myself
 | 
				
			||||||
    should_filter ||= receiver.blocking?(check_for_blocks)                                  # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
 | 
					    should_filter ||= Block.where(account_id: receiver_id, target_account_id: check_for_blocks).any?                                     # or it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked
 | 
				
			||||||
    should_filter ||= (status.account.silenced? && !receiver.following?(status.account))    # of if the account is silenced and I'm not following them
 | 
					    should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    should_filter
 | 
					    should_filter
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,9 +33,8 @@ class FanOutOnWriteService < BaseService
 | 
				
			||||||
  def deliver_to_followers(status)
 | 
					  def deliver_to_followers(status)
 | 
				
			||||||
    Rails.logger.debug "Delivering status #{status.id} to followers"
 | 
					    Rails.logger.debug "Delivering status #{status.id} to followers"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).find_each do |follower|
 | 
					    status.account.followers.where(domain: nil).joins(:user).where('users.current_sign_in_at > ?', 14.days.ago).select(:id).find_each do |follower|
 | 
				
			||||||
      next if FeedManager.instance.filter?(:home, status, follower)
 | 
					      FeedInsertWorker.perform_async(status.id, follower.id)
 | 
				
			||||||
      FeedManager.instance.push(:home, follower, status)
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +43,7 @@ class FanOutOnWriteService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status.mentions.includes(:account).each do |mention|
 | 
					    status.mentions.includes(:account).each do |mention|
 | 
				
			||||||
      mentioned_account = mention.account
 | 
					      mentioned_account = mention.account
 | 
				
			||||||
      next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mentioned_account)
 | 
					      next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mention.account_id)
 | 
				
			||||||
      FeedManager.instance.push(:home, mentioned_account, status)
 | 
					      FeedManager.instance.push(:home, mentioned_account, status)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					@ -54,9 +53,9 @@ class FanOutOnWriteService < BaseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    payload = FeedManager.instance.inline_render(nil, 'api/v1/statuses/show', status)
 | 
					    payload = FeedManager.instance.inline_render(nil, 'api/v1/statuses/show', status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    status.tags.find_each do |tag|
 | 
					    status.tags.pluck(:name).each do |hashtag|
 | 
				
			||||||
      FeedManager.instance.broadcast("hashtag:#{tag.name}", event: 'update', payload: payload)
 | 
					      FeedManager.instance.broadcast("hashtag:#{hashtag}", event: 'update', payload: payload)
 | 
				
			||||||
      FeedManager.instance.broadcast("hashtag:#{tag.name}:local", event: 'update', payload: payload) if status.account.local?
 | 
					      FeedManager.instance.broadcast("hashtag:#{hashtag}:local", event: 'update', payload: payload) if status.account.local?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ class NotifyService < BaseService
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def blocked_mention?
 | 
					  def blocked_mention?
 | 
				
			||||||
    FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient)
 | 
					    FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient.id)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def blocked_favourite?
 | 
					  def blocked_favourite?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ class PrecomputeFeedService < BaseService
 | 
				
			||||||
  def call(_, account)
 | 
					  def call(_, account)
 | 
				
			||||||
    redis.pipelined do
 | 
					    redis.pipelined do
 | 
				
			||||||
      Status.as_home_timeline(account).limit(FeedManager::MAX_ITEMS / 4).each do |status|
 | 
					      Status.as_home_timeline(account).limit(FeedManager::MAX_ITEMS / 4).each do |status|
 | 
				
			||||||
        next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account)
 | 
					        next if status.direct_visibility? || FeedManager.instance.filter?(:home, status, account.id)
 | 
				
			||||||
        redis.zadd(FeedManager.instance.key(:home, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
 | 
					        redis.zadd(FeedManager.instance.key(:home, account.id), status.id, status.reblog? ? status.reblog_of_id : status.id)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								app/workers/feed_insert_worker.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/workers/feed_insert_worker.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					# frozen_string_literal: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FeedInsertWorker
 | 
				
			||||||
 | 
					  include Sidekiq::Worker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def perform(status_id, follower_id)
 | 
				
			||||||
 | 
					    status   = Status.find(status_id)
 | 
				
			||||||
 | 
					    follower = Account.find(follower_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return if FeedManager.instance.filter?(:home, status, follower.id)
 | 
				
			||||||
 | 
					    FeedManager.instance.push(:home, follower, status)
 | 
				
			||||||
 | 
					  rescue ActiveRecord::RecordNotFound
 | 
				
			||||||
 | 
					    true
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue