From 051d1a3c36b09d70be76497d67017652f86204b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 13 Jun 2018 22:47:23 +0200 Subject: [PATCH] PERF: faster Screened IP Address roll up --- app/models/screened_ip_address.rb | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/app/models/screened_ip_address.rb b/app/models/screened_ip_address.rb index 60871eaba43..a061a9450ff 100644 --- a/app/models/screened_ip_address.rb +++ b/app/models/screened_ip_address.rb @@ -136,44 +136,41 @@ class ScreenedIpAddress < ActiveRecord::Base end def self.roll_up(current_user = Discourse.system_user) - # 1 - retrieve all subnets that needs roll up subnets = [star_subnets, star_star_subnets].flatten - # 2 - log the call StaffActionLogger.new(current_user).log_roll_up(subnets) unless subnets.blank? subnets.each do |subnet| - # 3 - create subnet if not already exists - ScreenedIpAddress.new(ip_address: subnet).save unless ScreenedIpAddress.where(ip_address: subnet).exists? + ScreenedIpAddress.create(ip_address: subnet) unless ScreenedIpAddress.where("? <<= ip_address", subnet).exists? - # 4 - update stats sql = <<-SQL UPDATE screened_ip_addresses - SET match_count = sum_match_count, - created_at = min_created_at, - last_match_at = max_last_match_at + SET match_count = sum_match_count + , created_at = min_created_at + , last_match_at = max_last_match_at FROM ( - SELECT SUM(match_count) AS sum_match_count, - MIN(created_at) AS min_created_at, - MAX(last_match_at) AS max_last_match_at + SELECT SUM(match_count) AS sum_match_count + , MIN(created_at) AS min_created_at + , MAX(last_match_at) AS max_last_match_at FROM screened_ip_addresses WHERE action_type = #{ScreenedIpAddress.actions[:block]} AND family(ip_address) = 4 AND ip_address << :ip_address ) s WHERE ip_address = :ip_address + AND sum_match_count IS NOT NULL + AND min_created_at IS NOT NULL + AND max_last_match_at IS NOT NULL SQL ScreenedIpAddress.exec_sql(sql, ip_address: subnet) - # 5 - remove old matches ScreenedIpAddress.where(action_type: ScreenedIpAddress.actions[:block]) .where("family(ip_address) = 4") .where("ip_address << ?", subnet) .delete_all end - # return the subnets subnets end