diff --git a/lib/cache.rb b/lib/cache.rb index 597ae2ce1dd..2f3689a02ca 100644 --- a/lib/cache.rb +++ b/lib/cache.rb @@ -22,7 +22,7 @@ class Cache < ActiveSupport::Cache::Store end def keys(pattern = "*") - redis.keys("#{@namespace}:#{pattern}") + redis.scan_each(match: "#{@namespace}:#{pattern}").to_a end def clear diff --git a/lib/discourse_redis.rb b/lib/discourse_redis.rb index 00647242b84..2a67c0515f0 100644 --- a/lib/discourse_redis.rb +++ b/lib/discourse_redis.rb @@ -201,6 +201,31 @@ class DiscourseRedis end end + def scan_each(options = {}, &block) + DiscourseRedis.ignore_readonly do + match = options[:match].presence || '*' + + options[:match] = + if @namespace + "#{namespace}:#{match}" + else + match + end + + if block + @redis.scan_each(options) do |key| + key = remove_namespace(key) if @namespace + block.call(key) + end + else + @redis.scan_each(options).map do |key| + key = remove_namespace(key) if @namespace + key + end + end + end + end + def keys(pattern = nil) DiscourseRedis.ignore_readonly do pattern = pattern || '*' @@ -253,4 +278,10 @@ class DiscourseRedis Cache.new end + private + + def remove_namespace(key) + key[(namespace.length + 1)..-1] + end + end diff --git a/spec/components/discourse_redis_spec.rb b/spec/components/discourse_redis_spec.rb index 7e87438d70f..a99c763414b 100644 --- a/spec/components/discourse_redis_spec.rb +++ b/spec/components/discourse_redis_spec.rb @@ -35,15 +35,22 @@ describe DiscourseRedis do expect(redis.keys).to include('key') expect(redis.keys).to_not include('key2') + expect(redis.scan_each.to_a).to eq(['key']) + + redis.scan_each.each do |key| + expect(key).to eq('key') + end redis.del('key') expect(raw_redis.get('default:key')).to eq(nil) + expect(redis.scan_each.to_a).to eq([]) raw_redis.set('default:key1', '1') raw_redis.set('default:key2', '2') expect(redis.mget('key1', 'key2')).to eq(['1', '2']) + expect(redis.scan_each.to_a).to contain_exactly('key1', 'key2') end end