Skip to content

Configure fail safe mechanism #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,20 @@ Kredis::Connections.connections[:shared] = Redis.new(

The above code could be added to either `config/environments/production.rb` or an initializer. Please ensure that your client private key, if used, is stored your credentials file or another secure location.

### Configure how the redis client is created
### Configuration

You can configure how the redis client is created by setting `config.kredis.connector` in your `application.rb`:

```ruby
config.kredis.connector = ->(config) { SomeRedisProxy.new(config) }
```

The fail safe mechanism supports silently rescuing or returning a default value in the event that the Redis client returns an error (e.g. Redis is down). You can disable the default fail safe mechanism:

```ruby
config.kredis.fail_safe = false
```

By default Kredis will use `Redis.new(config)`.

## License
Expand Down
1 change: 1 addition & 0 deletions lib/kredis/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Kredis::Railtie < ::Rails::Railtie

initializer "kredis.configuration" do
Kredis::Connections.connector = config.kredis.connector || ->(config) { Redis.new(config) }
Kredis::Types::Proxy.fail_safe_enabled = !!config.kredis.fail_safe
end

initializer "kredis.configurator" do
Expand Down
37 changes: 22 additions & 15 deletions lib/kredis/types/proxy/failsafe.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
module Kredis::Types::Proxy::Failsafe
def initialize(*)
super
@fail_safe_suppressed = false
end
extend ActiveSupport::Concern

def failsafe
yield
rescue Redis::BaseError
raise if fail_safe_suppressed?
included do
mattr_accessor :fail_safe_enabled, default: true
end

def suppress_failsafe_with(returning: nil)
old_fail_safe_suppressed, @fail_safe_suppressed = @fail_safe_suppressed, true
yield
rescue Redis::BaseError
returning
ensure
@fail_safe_suppressed = old_fail_safe_suppressed
def failsafe(returning: nil, &block)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about changing failsafe(returning: nil, &block) API to failsafe(returning: nil, errors: [Redis::BaseError], &block) such that we make explicit which errors we catch?

if fail_safe_enabled? && !fail_safe_suppressed?
rescue_redis_errors_with(returning: returning, &block)
else
yield
end
end

private
def fail_safe_enabled?
fail_safe_enabled
end

def fail_safe_suppressed?
@fail_safe_suppressed
end

def rescue_redis_errors_with(returning: nil)
old_fail_safe_suppressed, @fail_safe_suppressed = @fail_safe_suppressed, true
yield
rescue Redis::BaseError
returning
ensure
@fail_safe_suppressed = old_fail_safe_suppressed
end
end
6 changes: 2 additions & 4 deletions lib/kredis/types/proxying.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
class Kredis::Types::Proxying
attr_accessor :proxy, :key

delegate :failsafe, to: :proxy

def self.proxying(*commands)
delegate *commands, to: :proxy
end
Expand All @@ -13,10 +15,6 @@ def initialize(redis, key, **options)
options.each { |key, value| send("#{key}=", value) }
end

def failsafe(returning: nil, &block)
proxy.suppress_failsafe_with(returning: returning, &block)
end

private
delegate :type_to_string, :string_to_type, :types_to_strings, :strings_to_types, to: :Kredis
end
10 changes: 10 additions & 0 deletions test/proxy_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ class ProxyTest < ActiveSupport::TestCase
assert @proxy.set("two")
stub_redis_down(@proxy) { assert_nil @proxy.set("two") }
end

test "with fail safe disabled an error is raised" do
@proxy.fail_safe_enabled = false

stub_redis_down(@proxy) do
assert_raises(Redis::BaseError) { @proxy.get }
end

@proxy.fail_safe_enabled = true
end
end