PERF: Use Redis `SET EX GET` instead of LUA script for counting (#15939)
This will prevent Discourse from booting on Redis < 6.2.0
This commit is contained in:
parent
a48231041b
commit
4d3da70bc6
|
@ -42,19 +42,10 @@ module CachedCounting
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
GET_AND_RESET = <<~LUA
|
||||
local val = redis.call('get', KEYS[1])
|
||||
redis.call('set', KEYS[1], '0')
|
||||
return val
|
||||
LUA
|
||||
|
||||
# this may seem a bit fancy but in so it allows
|
||||
# for concurrent calls without double counting
|
||||
def get_and_reset(key)
|
||||
namespaced_key = Discourse.redis.namespace_key(key)
|
||||
val = Discourse.redis.without_namespace.eval(GET_AND_RESET, keys: [namespaced_key]).to_i
|
||||
Discourse.redis.expire(key, 259200) # SET removes expiry, so set it again
|
||||
val
|
||||
Discourse.redis.set(key, '0', ex: 259200, get: true).to_i
|
||||
end
|
||||
|
||||
def request_id(query_params, retries = 0)
|
||||
|
|
|
@ -8,3 +8,8 @@ end
|
|||
# Pending https://github.com/MiniProfiler/rack-mini-profiler/pull/450 and
|
||||
# upgrade to Sidekiq 6.1
|
||||
Redis.exists_returns_integer = true
|
||||
|
||||
if Gem::Version.new(Discourse.redis.info['redis_version']) < Gem::Version.new("6.2.0")
|
||||
STDERR.puts "Discourse requires Redis 6.2.0 or up"
|
||||
exit 1
|
||||
end
|
||||
|
|
|
@ -30,14 +30,14 @@ describe ApplicationRequest do
|
|||
inc(:http_total)
|
||||
|
||||
Discourse.redis.without_namespace.stubs(:incr).raises(Redis::CommandError.new("READONLY"))
|
||||
Discourse.redis.without_namespace.stubs(:eval).raises(Redis::CommandError.new("READONLY"))
|
||||
Discourse.redis.without_namespace.stubs(:set).raises(Redis::CommandError.new("READONLY"))
|
||||
|
||||
# flush will be deferred no error raised
|
||||
inc(:http_total, autoflush: 3)
|
||||
ApplicationRequest.write_cache!
|
||||
|
||||
Discourse.redis.without_namespace.unstub(:incr)
|
||||
Discourse.redis.without_namespace.unstub(:eval)
|
||||
Discourse.redis.without_namespace.unstub(:set)
|
||||
|
||||
inc(:http_total, autoflush: 3)
|
||||
expect(ApplicationRequest.http_total.first.count).to eq(3)
|
||||
|
|
|
@ -32,13 +32,13 @@ describe WebCrawlerRequest do
|
|||
inc('Googlebot')
|
||||
|
||||
Discourse.redis.without_namespace.stubs(:incr).raises(Redis::CommandError.new("READONLY"))
|
||||
Discourse.redis.without_namespace.stubs(:eval).raises(Redis::CommandError.new("READONLY"))
|
||||
Discourse.redis.without_namespace.stubs(:set).raises(Redis::CommandError.new("READONLY"))
|
||||
|
||||
inc('Googlebot', autoflush: 3)
|
||||
WebCrawlerRequest.write_cache!
|
||||
|
||||
Discourse.redis.without_namespace.unstub(:incr)
|
||||
Discourse.redis.without_namespace.unstub(:eval)
|
||||
Discourse.redis.without_namespace.unstub(:set)
|
||||
|
||||
inc('Googlebot', autoflush: 3)
|
||||
expect(web_crawler_request('Googlebot').count).to eq(3)
|
||||
|
|
Loading…
Reference in New Issue