discourse/lib/cache.rb
Guo Xiang Tan 2cbb513c98 FIX: Don't use Redis#keys in production.
As per the documentation for KEYS

```
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout.
```

Instead SCAN

```
Since these commands allow for incremental iteration, returning only a small number of elements per call, they can be used in production without the downside of commands like KEYS or SMEMBERS that may block the server for a long time (even several seconds) when called against big collections of keys or elements.
```
2018-12-25 15:12:59 +02:00

61 lines
1.2 KiB
Ruby

# Discourse specific cache, enforces 1 day expiry
class Cache < ActiveSupport::Cache::Store
# nothing is cached for longer than 1 day EVER
# there is no reason to have data older than this clogging redis
# it is dangerous cause if we rename keys we will be stuck with
# pointless data
MAX_CACHE_AGE = 1.day unless defined? MAX_CACHE_AGE
def initialize(opts = {})
@namespace = opts[:namespace] || "_CACHE_"
super(opts)
end
def redis
$redis
end
def reconnect
redis.reconnect
end
def keys(pattern = "*")
redis.scan_each(match: "#{@namespace}:#{pattern}").to_a
end
def clear
keys.each do |k|
redis.del(k)
end
end
def normalize_key(key, opts = nil)
"#{@namespace}:" << key
end
protected
def read_entry(key, options)
if data = redis.get(key)
data = Marshal.load(data)
ActiveSupport::Cache::Entry.new data
end
rescue
# corrupt cache, fail silently for now, remove rescue later
end
def write_entry(key, entry, options)
dumped = Marshal.dump(entry.value)
expiry = options[:expires_in] || MAX_CACHE_AGE
redis.setex(key, expiry, dumped)
true
end
def delete_entry(key, options)
redis.del key
end
end