Skip to content

Commit

Permalink
Merge pull request #30 from sorentwo/fault-tolerance
Browse files Browse the repository at this point in the history
Introduce redis connection fault tolerance
  • Loading branch information
sorentwo committed Dec 10, 2015
2 parents 4ee2e42 + 5b180e4 commit 2d72412
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 1 deletion.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## Unreleased

- Added: Global connection fault tolerance. Any Redis connection error will
raise be caught and a `nil` value will be returned instead. For `fetch`
operations that means the block will yielded, if provided.
[readthis#26][issue-26]

[issue-26]: https://github.com/sorentwo/readthis/issues/26

## v1.1.0 2015-12-07

- Fixed: Stop overwriting specific options with the default options. [issue-28].
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,19 @@ sticky and a flag is stored with each cached value. If you subsequently go to
deserialize values and haven't configured the same serializers in the same order
your application will raise errors.

## Fault Tolerance

In some situations it is desirable to keep serving requests from disk or the
database if Redis crashes. This can be achieved wiht connection fault tolerance
by enabling it at the top level:

```ruby
Readthis.fault_tolerant = true
```

The default value is `false`, because while it may work for `fetch` operations,
it isn't compatible with other state-based commands like `increment`.

## Differences From ActiveSupport::Cache

Readthis supports all of standard cache methods except for the following:
Expand Down
23 changes: 23 additions & 0 deletions lib/readthis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,27 @@ module Readthis
def serializers
@serializers ||= Readthis::Serializers.new
end

# Indicates whether connection error tolerance is enabled. With tolerance
# enabled every operation will return a `nil` value.
#
# @returns [Boolean] True for enabled, false for disabled
#
def fault_tolerant?
@fault_tolerant
end

# Toggle fault tolerance for connection errors.
#
# @param [Boolean] The new value for fault tolerance
#
def fault_tolerant=(value)
@fault_tolerant = value
end

# @private
def reset!
@fault_tolerant = nil
@serializers = nil
end
end
2 changes: 2 additions & 0 deletions lib/readthis/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ def invoke(operation, key, &block)
instrument(operation, key) do
pool.with(&block)
end
rescue Redis::BaseError => error
raise error unless Readthis.fault_tolerant?
end

def extract_options!(array)
Expand Down
12 changes: 11 additions & 1 deletion spec/readthis/cache_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
end

it 'uses a custom expiration' do
cache = Readthis::Cache.new(namespace: 'cache', expires_in: 86400)
cache = Readthis::Cache.new(namespace: 'cache', expires_in: 86_400)

cache.write('some-key', 'some-value')
cache.write('other-key', 'other-value', expires_in: 1)
Expand Down Expand Up @@ -166,6 +166,16 @@ def self.load(value)
cache.write('great-key', 'great')
expect(cache.fetch('great-key', nil)).to eq('great')
end

it 'serves computed content when the cache is down and tolerance is enabled' do
Readthis.fault_tolerant = true

allow(cache.pool).to receive(:with).and_raise(Redis::CannotConnectError)

computed = cache.fetch('error-key') { 'computed' }

expect(computed).to eq('computed')
end
end

describe '#read_multi' do
Expand Down
12 changes: 12 additions & 0 deletions spec/readthis_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@
expect(Readthis.serializers.marshals).to include(Marshal, JSON)
end
end

describe '#fault_tolerant?' do
it 'defaults to being false' do
expect(Readthis).not_to be_fault_tolerant
end

it 'can be enabled' do
Readthis.fault_tolerant = true

expect(Readthis).to be_fault_tolerant
end
end
end
4 changes: 4 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@

config.order = :random
Kernel.srand config.seed

config.before do
Readthis.reset!
end
end

0 comments on commit 2d72412

Please sign in to comment.