RedisCacheStoreProxy will blow up when RedisCacheStore raises a
CommandError exception. In fact, by default the proxied store only
handles BaseConnectionError exceptions, but will let bubble up any other
type of exception from the underlying client.
This pull request uses the same approach from RedisProxy, where store
operations are wrapped in a `rescuing` block that rescues and ignores
BaseError exceptions (the most generic exception class that can be
raised by the Redis client).
It seems that the original implementation accidentally autoloaded ActiveSupport::Cache::RedisCacheStore
which once evaluated asks for redis v4 generating Gem::LoadError.
In order to bypass any unnecessary constant autoloading we can just check class name string.
If connection pooling is used with AS::Cache::MemCacheStore,
unwrap_active_support_stores wouldn't return the underlying dalli instance(s),
and so Rack::Attack.store would be the bare unproxied MemCacheStore instance.
Calling write then increment would silently fail because :raw wasn't used.
With this commit, we no longer try to unwrap AS::Cache::MemCacheStore instances.
Let RedisCacheStoreProxy only know and assume things about
RedisCacheStore API. Don't let it know anything about the specific redis
client behind the scenes, that's the job of RedisCacheStore only, not
ours.
While a cache-store proxy exists for the redis-store gem, no such proxy
existed for using the redis gem itself. This fills that gap by adding
such a proxy.
Resolveskickstarter/rack-attack#190
'defined?' is buggy in ruby 2.5.0, which under certain circumstances
users using rack-attack can hit. See issue #253.
I reported (https://bugs.ruby-lang.org/issues/14407) and
fixed (https://github.com/ruby/ruby/pull/1800) the issue in
ruby already, but i guess i would take some time before there's
a new ruby release including that fix.
So for now we would need to circumvent this bug by using
'const_defined?' instead of 'defined?' for this particular case.
More details:
Anyone using:
* ruby 2.5.0
* redis
* rack-attack without redis-store and using at least one throttle
* having a toplevel class named Store
will hit this ruby 2.5.0 bug https://bugs.ruby-lang.org/issues/14407
That's because of the following buggy behavior of 'defined?' under ruby
2.5:
```
$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
$ irb
> class Redis
> end
=> nil
> class Store
> end
=> nil
> defined?(::Redis::Store)
=> "constant"
> ::Redis::Store
NameError (uninitialized constant Redis::Store
Did you mean? Store)
```