search: cache timed out search counts.

When a search is performed, we cache the post count so we don't have to
calculate it again every time the user switches pages. However, if the
count times out, we didn't cache it before, causing us to do a slow
count on every page load. This usually happens on multi-tag searches
that return a lot of results, `1girl solo` for example.

This changes it so that the count is cached even when it times out. This
will speed up large multi-tag searches.

This also changes it so that the count is cached for a fixed 5 minutes.
Before it was variable based on the size of the count, but this probably
didn't make much difference.
This commit is contained in:
evazion
2021-10-12 00:41:00 -05:00
parent 341be51f95
commit 0b22e873c9
2 changed files with 10 additions and 21 deletions

View File

@@ -902,8 +902,8 @@ class PostQueryBuilder
def fast_count(timeout: 1_000, estimate_count: true, skip_cache: false)
count = nil
count = estimated_count if estimate_count
count = cached_count if count.nil? && !skip_cache
count = exact_count(timeout) if count.nil?
count = cached_count(timeout) if count.nil? && !skip_cache
count = exact_count(timeout) if count.nil? && skip_cache
count
end
@@ -936,22 +936,16 @@ class PostQueryBuilder
ExplainParser.new(build).row_count
end
def cached_count
Cache.get(count_cache_key)
def cached_count(timeout, duration: 5.minutes)
Cache.get(count_cache_key, duration) do
exact_count(timeout)
end
end
def exact_count(timeout)
count = Post.with_timeout(timeout, nil) do
Post.with_timeout(timeout) do
build.count
end
set_cached_count(count) if count.present?
count
end
def set_cached_count(count)
expiry = count.seconds.clamp(3.minutes, 20.hours).to_i
Cache.put(count_cache_key, count, expiry)
end
def count_cache_key

View File

@@ -1199,7 +1199,7 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
context "for a single metatag" do
should "return the correct cached count" do
build(:tag, name: "score:42", post_count: -100).save(validate: false)
PostQueryBuilder.new("score:42").set_cached_count(100)
Cache.put("pfc:score:42", 100)
assert_fast_count(100, "score:42")
end
@@ -1207,7 +1207,7 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
pool = create(:pool, post_ids: [1, 2, 3])
build(:tag, name: "pool:#{pool.id}", post_count: -100).save(validate: false)
PostQueryBuilder.new("pool:1234").set_cached_count(100)
Cache.put("pfc:pool:1234", 100)
assert_fast_count(3, "pool:#{pool.id}")
assert_fast_count(3, "pool:#{pool.name}")
@@ -1237,7 +1237,7 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
context "for a multi-tag search" do
should "return the cached count, if it exists" do
PostQueryBuilder.new("score:42 aaa").set_cached_count(100)
Cache.put("pfc:score:42 aaa", 100)
assert_fast_count(100, "aaa score:42")
end
@@ -1245,11 +1245,6 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
assert_fast_count(1, "aaa score:42")
end
should "set the expiration time" do
Cache.expects(:put).with(PostQueryBuilder.new("score:42 aaa").count_cache_key, 1, 180)
assert_fast_count(1, "aaa score:42")
end
should "work with the hide_deleted_posts option turned on" do
create(:post, tag_string: "aaa", score: 42, is_deleted: true)
assert_fast_count(1, "aaa score:42", { hide_deleted_posts: true })