Skip to content

Commit

Permalink
Merge pull request #165 from kickstarter/fix-dalli-dependency
Browse files Browse the repository at this point in the history
Refactor StoreProxy to avoid autoloading MemCacheStore
  • Loading branch information
ktheory committed Feb 17, 2016
2 parents 14c7020 + cf89457 commit 63ee779
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## master (unreleased)

- Fix an error affecting apps using Redis::Store saying that dalli was a
required dependency. Learn about ActiveSupport autoloading. (#165)

## v4.4.0 - 10 Feb 2016

- New: support for MemCacheStore (#153). Thanks @elhu.
Expand Down
36 changes: 20 additions & 16 deletions lib/rack/attack/store_proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,30 @@ class Attack
module StoreProxy
PROXIES = [DalliProxy, MemCacheProxy, RedisStoreProxy]

ACTIVE_SUPPORT_WRAPPER_CLASSES = Set.new(['ActiveSupport::Cache::MemCacheStore', 'ActiveSupport::Cache::RedisStore']).freeze
ACTIVE_SUPPORT_CLIENTS = Set.new(['Redis::Store', 'Dalli::Client', 'MemCache']).freeze

def self.build(store)
# RedisStore#increment needs different behavior, so detect that
# (method has an arity of 2; must call #expire separately
if (defined?(::ActiveSupport::Cache::RedisStore) && store.is_a?(::ActiveSupport::Cache::RedisStore)) ||
(defined?(::ActiveSupport::Cache::MemCacheStore) && store.is_a?(::ActiveSupport::Cache::MemCacheStore))
client = unwrap_active_support_stores(store)
klass = PROXIES.find { |proxy| proxy.handle?(client) }
klass ? klass.new(client) : client
end


# ActiveSupport::Cache::RedisStore doesn't expose any way to set an expiry,
# so use the raw Redis::Store instead.
# We also want to use the underlying Dalli client instead of ::ActiveSupport::Cache::MemCacheStore,
# and the MemCache client if using Rails 3.x
client = store.instance_variable_get(:@data)
if (defined?(::Redis::Store) && client.is_a?(Redis::Store)) ||
(defined?(Dalli::Client) && client.is_a?(Dalli::Client)) || (defined?(MemCache) && client.is_a?(MemCache))
store = store.instance_variable_get(:@data)
end
private
def self.unwrap_active_support_stores(store)
# ActiveSupport::Cache::RedisStore doesn't expose any way to set an expiry,
# so use the raw Redis::Store instead.
# We also want to use the underlying Dalli client instead of ::ActiveSupport::Cache::MemCacheStore,
# and the MemCache client if using Rails 3.x

client = store.instance_variable_get(:@data)
if ACTIVE_SUPPORT_WRAPPER_CLASSES.include?(store.class.to_s) && ACTIVE_SUPPORT_CLIENTS.include?(client.class.to_s)
client
else
store
end
klass = PROXIES.find { |proxy| proxy.handle?(store) }
klass ? klass.new(store) : store
end

end
end
end
2 changes: 1 addition & 1 deletion lib/rack/attack/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Rack
class Attack
VERSION = '4.4.0'
VERSION = '4.4.1'
end
end

0 comments on commit 63ee779

Please sign in to comment.