frivol 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +7 -6
- data/CHANGES.md +15 -0
- data/Gemfile +4 -1
- data/README.rdoc +56 -24
- data/Rakefile +17 -0
- data/VERSION +1 -1
- data/frivol.gemspec +19 -6
- data/lib/frivol.rb +1 -3
- data/lib/frivol/backend/multi.rb +159 -0
- data/lib/frivol/backend/redis.rb +93 -0
- data/lib/frivol/backend/redis_distributed.rb +51 -0
- data/lib/frivol/backend/riak.rb +186 -0
- data/lib/frivol/class_methods.rb +10 -4
- data/lib/frivol/config.rb +8 -22
- data/lib/frivol/helpers.rb +32 -34
- data/test/fake_redis.rb +44 -19
- data/test/helper.rb +116 -6
- data/test/test_backend.rb +33 -0
- data/test/test_counters.rb +31 -0
- data/test/test_frivol.rb +24 -9
- data/test/test_frivolize.rb +11 -11
- data/test/test_multi_backend.rb +127 -0
- data/test/test_multi_backend_counters.rb +113 -0
- data/test/test_multi_backend_expiry.rb +128 -0
- data/test/test_riak.rb +41 -0
- data/test/test_threads.rb +6 -1
- metadata +30 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49b60bcea96f41ca6dfd54dc9b3b4c63db50c144
|
4
|
+
data.tar.gz: e47b8d3203ca595433192dbe55673fff5d2ad13e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4ebac79ca4b09b7685580b630ad763c75766b9daaf70b624c85d856bbcb44282ace07cc6ec2f890fb3c6519bac2ab4116b36580d910e9c2d128365ff9313801
|
7
|
+
data.tar.gz: e523e418a679e1b81e0645314e482e592f01f23fa89db470ec52ef382f394043ea8afe355195771bdf657b8aead9d2b10381296c00674915c4294d2e40f07c41
|
data/.travis.yml
CHANGED
@@ -2,14 +2,15 @@ language: ruby
|
|
2
2
|
bundler_args: --without development
|
3
3
|
before_install:
|
4
4
|
- 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc'
|
5
|
+
services:
|
6
|
+
- redis-server
|
7
|
+
- riak
|
5
8
|
rvm:
|
6
|
-
- 1.8.7
|
7
|
-
- 1.9.2
|
8
9
|
- 1.9.3
|
9
10
|
- 2.0.0
|
10
|
-
|
11
|
-
-
|
12
|
-
- jruby-19mode
|
11
|
+
- 2.1.0
|
12
|
+
- 2.2.0
|
13
13
|
- ruby-head
|
14
|
+
- jruby-19mode
|
14
15
|
- jruby-head
|
15
|
-
|
16
|
+
script: bundle exec rake test:all
|
data/CHANGES.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
<!--- TODO: Date and version -->
|
2
|
+
# March 2014 (v)
|
3
|
+
<!--- TODO: Check on this version number -->
|
4
|
+
- Drop support for Redis < 2.2.6
|
5
|
+
- Add backends for Redis, Redis::Distributed and Riak
|
6
|
+
- FIXED: counters never expire if created with increment or decrement methods
|
7
|
+
|
8
|
+
# Previous
|
9
|
+
<!--- TODO: Fill in -->
|
10
|
+
|
11
|
+
|
12
|
+
# TODO/BUGS(?):
|
13
|
+
- Hook AR reload method to clear_storage?
|
14
|
+
- Add a way (maybe using MR) to expire keys in Riak
|
15
|
+
- BUG: Now, counters always have their expiry reset
|
data/Gemfile
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gem 'multi_json'
|
4
|
-
gem 'redis'
|
5
4
|
gem 'rake'
|
6
5
|
|
7
6
|
group :development do
|
8
7
|
gem 'jeweler'
|
8
|
+
gem 'pry'
|
9
|
+
gem 'pry-debugger'
|
9
10
|
end
|
10
11
|
|
11
12
|
group :test do
|
12
13
|
gem 'test-unit'
|
14
|
+
gem 'redis'
|
15
|
+
gem 'riak-client'
|
13
16
|
end
|
data/README.rdoc
CHANGED
@@ -10,14 +10,27 @@ when a hot system is restarted. Frivol's design is such that it solves our probl
|
|
10
10
|
believe it is generic enough to be used in many Rails web projects and even in other types of
|
11
11
|
projects altogether.
|
12
12
|
|
13
|
+
As of version 0.4.0, Frivol supports various backends, including Redis::Destributed and Riak.
|
14
|
+
There's a Multi backend which will migrate keys from an old backend to a new one, like from
|
15
|
+
Redis to Redis::Destributed.
|
16
|
+
|
13
17
|
== Usage
|
18
|
+
|
19
|
+
=== Configuration
|
14
20
|
Configure Frivol in your configuration, for example in an initializer or in environment.rb
|
15
21
|
REDIS_CONFIG = {
|
16
22
|
:host => "localhost",
|
17
23
|
:port => 6379
|
18
24
|
}
|
19
|
-
Frivol::Config.
|
25
|
+
Frivol::Config.backend = Frivol::Backend::Redis.new(REDIS_CONFIG)
|
26
|
+
|
27
|
+
**Note:** This configuration has changed in version 0.4.0 with the introduction of <tt>Backend</tt>s
|
28
|
+
|
29
|
+
You can also use RedisDestributed or Riak backends. These are configured similarly. Finally there is a
|
30
|
+
Multi which works to migrate data from an old backend to a new one. For example, we used a Multi backend
|
31
|
+
to migrate from a single Redis instance to a RedisDistributed pair.
|
20
32
|
|
33
|
+
=== Standard Usage
|
21
34
|
Now include Frivol in whichever classes you'd like to make use of temporary storage. You can optionally
|
22
35
|
call the <tt>storage_expires_in(time)</tt> class method to set a default expiry. In your methods you can
|
23
36
|
now call the <tt>store(keys_and_values)</tt> and <tt>retrieve(keys_and_defaults)</tt> methods.
|
@@ -29,6 +42,33 @@ The default is not to expire the storage, in which case it will live for as long
|
|
29
42
|
<tt>delete_storage</tt>, as the name suggests will immediately delete the storage, while <tt>clear_storage</tt>
|
30
43
|
will clear the cache that Frivol keeps and force the next <tt>retrieve</tt> to return to Redis for the data.
|
31
44
|
|
45
|
+
==== Example
|
46
|
+
class BigComplexCalcer
|
47
|
+
include Frivol
|
48
|
+
storage_expires_in 600 # temporary storage expires in 10 minutes.
|
49
|
+
def initialize(key)
|
50
|
+
@key = key
|
51
|
+
end
|
52
|
+
def storage_key(bucket = nil)
|
53
|
+
"frivol-test-#{key}" # override the storage key because we don't respond_to? :id, and don't care about buckets
|
54
|
+
end
|
55
|
+
def big_complex_calc
|
56
|
+
retrieve :complex => :do_big_complex_calc # do_big_complex_calc is the method to get the default from
|
57
|
+
end
|
58
|
+
def last_calc_done
|
59
|
+
last = retrieve(:last => nil) # default is nil
|
60
|
+
return "never" if last.nil?
|
61
|
+
return "#{Time.now - Time.at(last)} seconds ago"
|
62
|
+
end
|
63
|
+
def do_big_complex_calc
|
64
|
+
# Wee! Do some really hard work here...
|
65
|
+
# ...still working...
|
66
|
+
store :complex => result, :last => Time.now.to_i # ...and let's keep the result for at least 10 minutes, as well as the last timme we did it
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
=== Buckets
|
32
72
|
Since version 0.1.5 Frivol can create different storage buckets. Note that this introduces a breaking change
|
33
73
|
to the <tt>storage_key</tt> method if you have overriden it. It now takes a +bucket+ parameter.
|
34
74
|
|
@@ -42,6 +82,7 @@ exactly like the standard +store+ and +retrieve+ methods. There will also be <tt
|
|
42
82
|
take a integer (value and default, respectively) and the increment does not take a parameter. Since version 0.2.1
|
43
83
|
there is also <tt>increment_my_counter_by</tt>, <tt>decrement_my_counter</tt> and <tt>decrement_my_counter_by<tt>.
|
44
84
|
|
85
|
+
=== Conditional retrieval
|
45
86
|
Fine grained control of storing and retrieving values from buckets can be controlled using the :condition and
|
46
87
|
:else options.
|
47
88
|
storage_bucket :my_bucket,
|
@@ -61,30 +102,21 @@ Frivol uses the +storage_key+ method to create a base key for storage in Redis.
|
|
61
102
|
<tt>"#{self.class.name}-#{id}"</tt> so you'll want to override that method if you have classes that don't
|
62
103
|
respond to id.
|
63
104
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def last_calc_done
|
78
|
-
last = retrieve(:last => nil) # default is nil
|
79
|
-
return "never" if last.nil?
|
80
|
-
return "#{Time.now - Time.at(last)} seconds ago"
|
81
|
-
end
|
82
|
-
def do_big_complex_calc
|
83
|
-
# Wee! Do some really hard work here...
|
84
|
-
# ...still working...
|
85
|
-
store :complex => result, :last => Time.now.to_i # ...and let's keep the result for at least 10 minutes, as well as the last me we did it
|
86
|
-
end
|
105
|
+
=== Frivolize
|
106
|
+
The +frivolize+ method is similar to +memoize+ except that it uses the backend to store the data which can thus be
|
107
|
+
shared amongst multiple processes.
|
108
|
+
|
109
|
+
def long_running_result
|
110
|
+
# do lots of hard work
|
111
|
+
end
|
112
|
+
frivolize :long_running_result
|
113
|
+
|
114
|
+
The frivolize also is also able to take options to make counters and expire.
|
115
|
+
|
116
|
+
def long_running_count
|
117
|
+
# count something that takes a long time
|
87
118
|
end
|
119
|
+
frivolize :long_running_count, counter: true, expires_in: 10.minutes
|
88
120
|
|
89
121
|
== Time Extensions
|
90
122
|
These extensions allow the storing and retrieving of <tt>Time</tt> and
|
data/Rakefile
CHANGED
@@ -24,6 +24,23 @@ Rake::TestTask.new(:test) do |test|
|
|
24
24
|
test.verbose = true
|
25
25
|
end
|
26
26
|
|
27
|
+
namespace :test do
|
28
|
+
desc 'Test all backends and the Multi backend in all combinations'
|
29
|
+
task :all do
|
30
|
+
%w[
|
31
|
+
fake_redis redis redis_distributed riak multi
|
32
|
+
multi_redis_redis multi_redis_redis_distributed
|
33
|
+
multi_redis_riak multi_redis_distributed_riak
|
34
|
+
multi_riak_redis multi_riak_redis_distributed
|
35
|
+
].each do |backend|
|
36
|
+
puts "Testing #{backend}"
|
37
|
+
ENV['backend'] = backend
|
38
|
+
Rake::Task["test"].reenable
|
39
|
+
Rake::Task["test"].invoke
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
27
44
|
task :default => :test
|
28
45
|
|
29
46
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/frivol.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: frivol 0.
|
5
|
+
# stub: frivol 0.4.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "frivol"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.4.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Marc Heiligers"]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2015-06-28"
|
15
15
|
s.description = "Simple Redis backed temporary storage intended primarily for use with ActiveRecord models to provide caching"
|
16
16
|
s.email = "marc@eternal.co.za"
|
17
17
|
s.extra_rdoc_files = [
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.files = [
|
22
22
|
".document",
|
23
23
|
".travis.yml",
|
24
|
+
"CHANGES.md",
|
24
25
|
"Gemfile",
|
25
26
|
"LICENSE",
|
26
27
|
"README.rdoc",
|
@@ -53,6 +54,10 @@ Gem::Specification.new do |s|
|
|
53
54
|
"doc/rdoc-style.css",
|
54
55
|
"frivol.gemspec",
|
55
56
|
"lib/frivol.rb",
|
57
|
+
"lib/frivol/backend/multi.rb",
|
58
|
+
"lib/frivol/backend/redis.rb",
|
59
|
+
"lib/frivol/backend/redis_distributed.rb",
|
60
|
+
"lib/frivol/backend/riak.rb",
|
56
61
|
"lib/frivol/class_methods.rb",
|
57
62
|
"lib/frivol/config.rb",
|
58
63
|
"lib/frivol/functor.rb",
|
@@ -60,6 +65,7 @@ Gem::Specification.new do |s|
|
|
60
65
|
"lib/frivol/time_extensions.rb",
|
61
66
|
"test/fake_redis.rb",
|
62
67
|
"test/helper.rb",
|
68
|
+
"test/test_backend.rb",
|
63
69
|
"test/test_buckets.rb",
|
64
70
|
"test/test_condition.rb",
|
65
71
|
"test/test_condition_with_counters.rb",
|
@@ -68,6 +74,10 @@ Gem::Specification.new do |s|
|
|
68
74
|
"test/test_extensions.rb",
|
69
75
|
"test/test_frivol.rb",
|
70
76
|
"test/test_frivolize.rb",
|
77
|
+
"test/test_multi_backend.rb",
|
78
|
+
"test/test_multi_backend_counters.rb",
|
79
|
+
"test/test_multi_backend_expiry.rb",
|
80
|
+
"test/test_riak.rb",
|
71
81
|
"test/test_seeds.rb",
|
72
82
|
"test/test_threads.rb"
|
73
83
|
]
|
@@ -80,20 +90,23 @@ Gem::Specification.new do |s|
|
|
80
90
|
|
81
91
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
82
92
|
s.add_runtime_dependency(%q<multi_json>, [">= 0"])
|
83
|
-
s.add_runtime_dependency(%q<redis>, [">= 0"])
|
84
93
|
s.add_runtime_dependency(%q<rake>, [">= 0"])
|
85
94
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
95
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
96
|
+
s.add_development_dependency(%q<pry-debugger>, [">= 0"])
|
86
97
|
else
|
87
98
|
s.add_dependency(%q<multi_json>, [">= 0"])
|
88
|
-
s.add_dependency(%q<redis>, [">= 0"])
|
89
99
|
s.add_dependency(%q<rake>, [">= 0"])
|
90
100
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
101
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
102
|
+
s.add_dependency(%q<pry-debugger>, [">= 0"])
|
91
103
|
end
|
92
104
|
else
|
93
105
|
s.add_dependency(%q<multi_json>, [">= 0"])
|
94
|
-
s.add_dependency(%q<redis>, [">= 0"])
|
95
106
|
s.add_dependency(%q<rake>, [">= 0"])
|
96
107
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
108
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
109
|
+
s.add_dependency(%q<pry-debugger>, [">= 0"])
|
97
110
|
end
|
98
111
|
end
|
99
112
|
|
data/lib/frivol.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require "redis"
|
2
|
-
|
3
1
|
# == Frivol
|
4
2
|
module Frivol
|
5
3
|
require "frivol/config"
|
@@ -56,7 +54,7 @@ module Frivol
|
|
56
54
|
# Expire the stored data in +time+ seconds.
|
57
55
|
def expire_storage(time, bucket = nil)
|
58
56
|
return if time.nil?
|
59
|
-
Frivol::Config.
|
57
|
+
Frivol::Config.backend.expire storage_key(bucket), time
|
60
58
|
end
|
61
59
|
|
62
60
|
# The base key used for storage in Redis.
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Frivol
|
2
|
+
module Backend
|
3
|
+
# == Configuration
|
4
|
+
# This backend is used to migrate from one backend to another (and another) (and another).
|
5
|
+
# Essentially, this backend will check for the existence of the key in the newest backend,
|
6
|
+
# and if not found check in the older backends in order. If it's found in an older backend
|
7
|
+
# it will move the value to the new backend.
|
8
|
+
#
|
9
|
+
# I have used this in production to move from Redis to RedisDistributed.
|
10
|
+
# old_backend = Frivol::Backend::Redis.new(:db => 10)
|
11
|
+
# new_backend = Frivol::Backend::RedisDistributed.new(["redis://127.0.0.1:6379/11", "redis://127.0.0.1:6379/12"])
|
12
|
+
# Frivol::Config.backend = Frivol::Backend::Multi.new([ new_backend, old_backend ])
|
13
|
+
class Multi
|
14
|
+
# :nodoc:
|
15
|
+
BackendsNotUniqueError = Class.new(StandardError)
|
16
|
+
|
17
|
+
def initialize(backends)
|
18
|
+
unless backends.map(&:inspect).uniq.size == backends.size
|
19
|
+
raise BackendsNotUniqueError, "Backends are not unique: #{backends.map(&:inspect).join(', ')}"
|
20
|
+
end
|
21
|
+
@primary_backend = backends.shift
|
22
|
+
@other_backends = backends
|
23
|
+
end
|
24
|
+
|
25
|
+
# Hashes
|
26
|
+
def get(key, expiry = Frivol::NEVER_EXPIRE)
|
27
|
+
val = @primary_backend.get(key)
|
28
|
+
val = migrate(key, expiry) if val.nil?
|
29
|
+
val
|
30
|
+
end
|
31
|
+
|
32
|
+
def set(key, val, expiry = Frivol::NEVER_EXPIRE)
|
33
|
+
@other_backends.each { |be| be.del(key) }
|
34
|
+
@primary_backend.set(key, val, expiry)
|
35
|
+
end
|
36
|
+
|
37
|
+
def del(key)
|
38
|
+
@primary_backend.del(key)
|
39
|
+
@other_backends.each { |be| be.del(key) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def exists(key)
|
43
|
+
@primary_backend.exists(key) ||
|
44
|
+
@other_backends.detect { |be| be.exists(key) }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Counters
|
48
|
+
def getc(key, expiry = Frivol::NEVER_EXPIRE)
|
49
|
+
val = @primary_backend.getc(key)
|
50
|
+
val = migratec(key, :getc, 0, expiry) if val.nil?
|
51
|
+
val
|
52
|
+
end
|
53
|
+
|
54
|
+
def setc(key, val, expiry = Frivol::NEVER_EXPIRE)
|
55
|
+
@other_backends.each { |be| be.delc(key) }
|
56
|
+
@primary_backend.setc(key, val, expiry)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delc(key)
|
60
|
+
@primary_backend.delc(key)
|
61
|
+
@other_backends.each { |be| be.delc(key) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def existsc(key)
|
65
|
+
@primary_backend.existsc(key) ||
|
66
|
+
@other_backends.detect { |be| be.existsc(key) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def incr(key, expiry = Frivol::NEVER_EXPIRE)
|
70
|
+
if @primary_backend.existsc(key)
|
71
|
+
@primary_backend.incr(key)
|
72
|
+
else
|
73
|
+
migratec(key, :incrby, 1, expiry)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def decr(key, expiry = Frivol::NEVER_EXPIRE)
|
78
|
+
if @primary_backend.existsc(key)
|
79
|
+
@primary_backend.decr(key)
|
80
|
+
else
|
81
|
+
migratec(key, :decrby, 1, expiry)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def incrby(key, amt, expiry = Frivol::NEVER_EXPIRE)
|
86
|
+
if @primary_backend.existsc(key)
|
87
|
+
@primary_backend.incrby(key, amt)
|
88
|
+
else
|
89
|
+
migratec(key, :incrby, amt, expiry)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def decrby(key, amt, expiry = Frivol::NEVER_EXPIRE)
|
94
|
+
if @primary_backend.existsc(key)
|
95
|
+
@primary_backend.decrby(key, amt)
|
96
|
+
else
|
97
|
+
migratec(key, :decrby, amt, expiry)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Expiry/TTL
|
102
|
+
def expire(key, ttl)
|
103
|
+
@primary_backend.expire(key, ttl)
|
104
|
+
end
|
105
|
+
|
106
|
+
def ttl(key)
|
107
|
+
expiry = @primary_backend.ttl(key)
|
108
|
+
if expiry.nil?
|
109
|
+
@other_backends.each do |be|
|
110
|
+
expiry = be.ttl(key)
|
111
|
+
return expiry unless expiry.nil?
|
112
|
+
end
|
113
|
+
nil
|
114
|
+
else
|
115
|
+
expiry
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Connection
|
120
|
+
def flushdb
|
121
|
+
@primary_backend.flushdb
|
122
|
+
@other_backends.each { |be| be.flushdb }
|
123
|
+
end
|
124
|
+
|
125
|
+
def connection
|
126
|
+
@primary_backend.connection
|
127
|
+
end
|
128
|
+
|
129
|
+
# Migration
|
130
|
+
def migrate(key, expiry = Frivol::NEVER_EXPIRE)
|
131
|
+
backend = @other_backends.detect { |be| be.exists(key) }
|
132
|
+
if backend
|
133
|
+
val = backend.get(key)
|
134
|
+
ttl = backend.ttl(key)
|
135
|
+
@primary_backend.set(key, val, ttl)
|
136
|
+
@other_backends.each { |be| be.del key }
|
137
|
+
val
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def migratec(key, method = :incrby, amt = 0, expiry = Frivol::NEVER_EXPIRE)
|
142
|
+
backend = @other_backends.detect { |be| be.existsc(key) }
|
143
|
+
if backend
|
144
|
+
val = backend.getc(key).to_i
|
145
|
+
ttl = backend.ttl(key)
|
146
|
+
@primary_backend.incrby(key, val) unless val.zero?
|
147
|
+
val = @primary_backend.send(method, key, amt) unless amt.zero? || method == :getc
|
148
|
+
@primary_backend.expire(key, ttl) if ttl
|
149
|
+
@other_backends.each { |be| be.delc key }
|
150
|
+
val
|
151
|
+
elsif method != :getc
|
152
|
+
@primary_backend.send(method, key, amt, expiry)
|
153
|
+
else
|
154
|
+
nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|