Skip to content

Don't fail when Redis is misbehaving, e.g. OOM command not allowed when used memory > 'maxmemory' #511

Open
@Nowaker

Description

@Nowaker

Rack Attack is written so it doesn't fail if Redis is down on application startup. That's cool.

However, it will bring down the application if Redis server starts misbehaving at later point, for example:

Redis::CommandError: OOM command not allowed when used memory > 'maxmemory'

Preferably, we should ignore any Redis errors and pass the request to the next middleware.

Alternatively, we should allow users to define an exception handler for any errors that happen inside Rack Attack (not the next middleware), with an option to bypass the exception and continue processing. Example:

Rack::Attack.exception_handler = lambda do |exception|
  Rails.logger.error exception # do whatever you want here
  raise # Re-raises the exception, therefore failing the request. Without an explicit `raise` in the handler, the processing would continue
end

Here's the full stacktrace from when the problem happened and killed my application:

lib/redis/client.rb:121 call  
lib/redis.rb:769 block in setex 
lib/redis.rb:58 block in synchronize  
/home/ec2-user/.rbenv/versions/2.6.3/lib/ruby/2.6.0/monitor.rb:230 mon_synchronize  
lib/redis.rb:58 synchronize 
lib/redis.rb:768 setex  
redis-store (1.6.0) lib/redis/store/interface.rb:17 setex 
redis-store (1.6.0) lib/redis/store/serialization.rb:13 block in setex  
redis-store (1.6.0) lib/redis/store/serialization.rb:40 _marshal  
redis-store (1.6.0) lib/redis/store/serialization.rb:13 setex 
redis-store (1.6.0) lib/redis/store/namespace.rb:11 block in setex  
redis-store (1.6.0) lib/redis/store/namespace.rb:89 namespace 
redis-store (1.6.0) lib/redis/store/namespace.rb:11 setex 
redis-store (1.6.0) lib/redis/store/ttl.rb:6 set  
redis-store (1.6.0) lib/redis/store/serialization.rb:5 block in set 
redis-store (1.6.0) lib/redis/store/serialization.rb:40 _marshal  
redis-store (1.6.0) lib/redis/store/serialization.rb:5 set  
redis-store (1.6.0) lib/redis/store/namespace.rb:7 block in set 
redis-store (1.6.0) lib/redis/store/namespace.rb:89 namespace 
redis-store (1.6.0) lib/redis/store/namespace.rb:7 set  
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:282 block (2 levels) in write_entry 
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:270 with  
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:282 block in write_entry  
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:340 failsafe  
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:280 write_entry 
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:86 block in write 
lib/active_support/cache.rb:547 block in instrument 
lib/appsignal/hooks/active_support_notifications.rb:21 block in instrument  
lib/active_support/notifications/instrumenter.rb:20 instrument  
lib/appsignal/hooks/active_support_notifications.rb:35 instrument 
lib/appsignal/hooks/active_support_notifications.rb:20 instrument 
lib/active_support/cache.rb:547 instrument  
redis-activesupport (5.2.0) lib/active_support/cache/redis_store.rb:81 write  
/home/ec2-user/.rbenv/versions/2.6.3/lib/ruby/2.6.0/delegate.rb:83 method_missing 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb:34 write 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/store_proxy/active_support_redis_store_proxy.rb:21 increment 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/cache.rb:74 do_count 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/cache.rb:27 count  
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/throttle.rb:31 matched_by? 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/configuration.rb:93 block in throttled?  
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/configuration.rb:92 any? 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack/configuration.rb:92 throttled? 
/var/www/apps/app/shared/bundle/ruby/2.6.0/bundler/gems/rack-attack-6d1bc9b617c5/lib/rack/attack.rb:118 call
(... other middlewares ...)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions