mirror of
https://github.com/discourse/discourse.git
synced 2025-01-30 16:19:31 +08:00
PERF: handle debounce in redis cause SQL can be slow
This commit is contained in:
parent
442a17bfb2
commit
bf68d394f4
|
@ -19,42 +19,54 @@ class SearchLog < ActiveRecord::Base
|
|||
)
|
||||
end
|
||||
|
||||
def self.redis_key(ip_address:, user_id: nil)
|
||||
if user_id
|
||||
"__SEARCH__LOG_#{user_id}"
|
||||
else
|
||||
"__SEARCH__LOG_#{ip_address}"
|
||||
end
|
||||
end
|
||||
|
||||
# for testing
|
||||
def self.clear_debounce_cache!
|
||||
$redis.keys("__SEARCH__LOG_*").each do |k|
|
||||
$redis.del(k)
|
||||
end
|
||||
end
|
||||
|
||||
def self.log(term:, search_type:, ip_address:, user_id: nil)
|
||||
|
||||
search_type = search_types[search_type]
|
||||
return [:error] unless search_type.present? && ip_address.present?
|
||||
|
||||
update_sql = <<~SQL
|
||||
UPDATE search_logs
|
||||
SET term = :term,
|
||||
created_at = :created_at
|
||||
WHERE created_at > :timeframe AND
|
||||
position(term IN :term) = 1 AND
|
||||
((:user_id IS NULL AND ip_address = :ip_address) OR
|
||||
(user_id = :user_id))
|
||||
RETURNING id
|
||||
SQL
|
||||
key = redis_key(user_id: user_id, ip_address: ip_address)
|
||||
|
||||
rows = exec_sql(
|
||||
update_sql,
|
||||
term: term,
|
||||
created_at: Time.zone.now,
|
||||
timeframe: 5.seconds.ago,
|
||||
user_id: user_id,
|
||||
ip_address: ip_address
|
||||
)
|
||||
result = nil
|
||||
|
||||
if rows.cmd_tuples == 0
|
||||
result = create(
|
||||
if existing = $redis.get(key)
|
||||
id, old_term = existing.split(",", 2)
|
||||
if term.start_with?(old_term)
|
||||
where(id: id.to_i).update_all(
|
||||
created_at: Time.zone.now,
|
||||
term: term
|
||||
)
|
||||
result = [:updated, id.to_i]
|
||||
end
|
||||
end
|
||||
|
||||
if !result
|
||||
log = create(
|
||||
term: term,
|
||||
search_type: search_type,
|
||||
ip_address: ip_address,
|
||||
user_id: user_id
|
||||
)
|
||||
[:created, result.id]
|
||||
else
|
||||
[:updated, rows[0]['id'].to_i]
|
||||
result = [:created, log.id]
|
||||
end
|
||||
|
||||
$redis.setex(key, 5, "#{result[1]},#{term}")
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def self.term_details(term, period = :weekly, search_type = :all)
|
||||
|
|
|
@ -2,6 +2,10 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe SearchLog, type: :model do
|
||||
|
||||
before do
|
||||
SearchLog.clear_debounce_cache!
|
||||
end
|
||||
|
||||
describe ".log" do
|
||||
|
||||
context "invalid arguments" do
|
||||
|
@ -122,6 +126,7 @@ RSpec.describe SearchLog, type: :model do
|
|||
expect(action).to eq(:created)
|
||||
|
||||
freeze_time(10.minutes.from_now)
|
||||
$redis.del(SearchLog.redis_key(ip_address: '192.168.0.1', user_id: user.id))
|
||||
|
||||
action, _ = SearchLog.log(
|
||||
term: 'hello',
|
||||
|
|
Loading…
Reference in New Issue
Block a user