Optimize filter methods in FeedManager a bit, use redis pipelining on merge/unmerge feed methods,
do not re-create a dynamic class on each feed push call, make sure redis-rb uses hiredis
This commit is contained in:
		
							
								
								
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							| @@ -38,7 +38,7 @@ gem 'rqrcode' | ||||
| gem 'twitter-text' | ||||
| gem 'oj' | ||||
| gem 'hiredis' | ||||
| gem 'redis', '~>3.2' | ||||
| gem 'redis', '~>3.2', require: ['redis', 'redis/connection/hiredis'] | ||||
| gem 'fast_blank' | ||||
| gem 'htmlentities' | ||||
| gem 'simple_form' | ||||
|   | ||||
| @@ -51,9 +51,11 @@ class FeedManager | ||||
|   def merge_into_timeline(from_account, into_account) | ||||
|     timeline_key = key(:home, into_account.id) | ||||
|  | ||||
|     from_account.statuses.limit(MAX_ITEMS).each do |status| | ||||
|       next if status.direct_visibility? || filter?(:home, status, into_account) | ||||
|       redis.zadd(timeline_key, status.id, status.id) | ||||
|     redis.pipelined do | ||||
|       from_account.statuses.limit(MAX_ITEMS).each do |status| | ||||
|         next if status.direct_visibility? || filter?(:home, status, into_account) | ||||
|         redis.zadd(timeline_key, status.id, status.id) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     trim(:home, into_account.id) | ||||
| @@ -62,30 +64,18 @@ class FeedManager | ||||
|   def unmerge_from_timeline(from_account, into_account) | ||||
|     timeline_key = key(:home, into_account.id) | ||||
|  | ||||
|     from_account.statuses.select('id').find_each do |status| | ||||
|       redis.zrem(timeline_key, status.id) | ||||
|       redis.zremrangebyscore(timeline_key, status.id, status.id) | ||||
|     from_account.statuses.select('id').find_in_batches do |statuses| | ||||
|       redis.pipelined do | ||||
|         statuses.each do |status| | ||||
|           redis.zrem(timeline_key, status.id) | ||||
|           redis.zremrangebyscore(timeline_key, status.id, status.id) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def inline_render(target_account, template, object) | ||||
|     rabl_scope = Class.new do | ||||
|       include RoutingHelper | ||||
|  | ||||
|       def initialize(account) | ||||
|         @account = account | ||||
|       end | ||||
|  | ||||
|       def current_user | ||||
|         @account.try(:user) | ||||
|       end | ||||
|  | ||||
|       def current_account | ||||
|         @account | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     Rabl::Renderer.new(template, object, view_path: 'app/views', format: :json, scope: rabl_scope.new(target_account)).render | ||||
|     Rabl::Renderer.new(template, object, view_path: 'app/views', format: :json, scope: InlineRablScope.new(target_account)).render | ||||
|   end | ||||
|  | ||||
|   private | ||||
| @@ -95,36 +85,38 @@ class FeedManager | ||||
|   end | ||||
|  | ||||
|   def filter_from_home?(status, receiver) | ||||
|     return true if receiver.muting?(status.account) | ||||
|     return true if status.reply? && status.in_reply_to_id.nil? | ||||
|  | ||||
|     should_filter = false | ||||
|     check_for_mutes = [status.account_id] | ||||
|     check_for_mutes.concat([status.reblog.account_id]) if status.reblog? | ||||
|  | ||||
|     if status.reply? && status.in_reply_to_id.nil? | ||||
|       should_filter = true | ||||
|     elsif status.reply? && !status.in_reply_to_account_id.nil?                # Filter out if it's a reply | ||||
|     return true if receiver.muting?(check_for_mutes) | ||||
|  | ||||
|     check_for_blocks = status.mentions.map(&:account_id) | ||||
|     check_for_blocks.concat([status.reblog.account_id]) if status.reblog? | ||||
|  | ||||
|     return true if receiver.blocking?(check_for_blocks) | ||||
|  | ||||
|     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 &&= !(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 | ||||
|       return should_filter | ||||
|     elsif status.reblog?                                                      # Filter out a reblog | ||||
|       should_filter = receiver.blocking?(status.reblog.account)               # if I'm blocking the reblogged person | ||||
|       should_filter ||= receiver.muting?(status.reblog.account)               # or muting that person | ||||
|       should_filter ||= status.reblog.account.blocking?(receiver)             # or if the author of the reblogged status is blocking me | ||||
|       return status.reblog.account.blocking?(receiver)                        # or if the author of the reblogged status is blocking me | ||||
|     end | ||||
|  | ||||
|     should_filter ||= receiver.blocking?(status.mentions.map(&:account_id))   # or if it mentions someone I blocked | ||||
|  | ||||
|     should_filter | ||||
|     false | ||||
|   end | ||||
|  | ||||
|   def filter_from_mentions?(status, receiver) | ||||
|     should_filter   = receiver.id == status.account_id                                      # Filter if I'm mentioning myself | ||||
|     should_filter ||= receiver.blocking?(status.account)                                    # or it's from someone I blocked | ||||
|     should_filter ||= receiver.blocking?(status.mentions.includes(:account).map(&:account)) # or if it mentions someone I blocked | ||||
|     should_filter ||= (status.account.silenced? && !receiver.following?(status.account))    # of if the account is silenced and I'm not following them | ||||
|     check_for_blocks = [status.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? | ||||
|  | ||||
|     if status.reply? && !status.in_reply_to_account_id.nil?                                 # or it's a reply | ||||
|       should_filter ||= receiver.blocking?(status.in_reply_to_account)                      # to a user I blocked | ||||
|     end | ||||
|     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 ||= (status.account.silenced? && !receiver.following?(status.account))    # of if the account is silenced and I'm not following them | ||||
|  | ||||
|     should_filter | ||||
|   end | ||||
|   | ||||
							
								
								
									
										17
									
								
								app/lib/inline_rabl_scope.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app/lib/inline_rabl_scope.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class InlineRablScope | ||||
|   include RoutingHelper | ||||
|  | ||||
|   def initialize(account) | ||||
|     @account = account | ||||
|   end | ||||
|  | ||||
|   def current_user | ||||
|     @account.try(:user) | ||||
|   end | ||||
|  | ||||
|   def current_account | ||||
|     @account | ||||
|   end | ||||
| end | ||||
		Reference in New Issue
	
	Block a user