double_write_cache_stores 0.2.0 → 0.3.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/README.md +19 -0
- data/lib/dalli_store_patch.rb +41 -0
- data/lib/double_write_cache_stores.rb +2 -0
- data/lib/double_write_cache_stores/base_exception.rb +4 -0
- data/lib/double_write_cache_stores/client.rb +115 -13
- data/lib/double_write_cache_stores/version.rb +1 -1
- data/spec/double_write_cache_stores/client_spec.rb +211 -118
- data/spec/double_write_cache_stores_spec.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f2e06c115f9f6f2c93e70bd217a9f0d2277e4b8
|
4
|
+
data.tar.gz: 026266132650bcfe4a9b11f8a7ea78cbaeaaceeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7abdfd76502de8e42de745dbdd1ab4c729a126e3154e0572383720c70a27d06cd6e0e5e072963c57aaa8e1ca9833c81a4686278a489535e0b28d12e93735d2d7
|
7
|
+
data.tar.gz: 4ffd5deef56bd569014e711abf799c39217f2ae484c0ebc612d8868626a9f2152be6ac62c12f6a62f32c948c133ed24f7ac23788a681d8f47d6507efae24868b
|
data/README.md
CHANGED
@@ -39,6 +39,25 @@ write_only_cache_store = ActiveSupport::Cache.lookup_store :dalli_store, 'localh
|
|
39
39
|
set :cache, DoubleWriteCacheStores::Client.new(read_and_write_cache_store, write_only_cache_store)
|
40
40
|
````
|
41
41
|
|
42
|
+
### Rails4
|
43
|
+
|
44
|
+
`config/application.rb`
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
read_and_write_cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, 'localhost:11211'
|
48
|
+
write_only_cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, 'localhost:21211'
|
49
|
+
|
50
|
+
config.cache_store = DoubleWriteCacheStores::Client.new(read_and_write_cache_store, write_only_cache_store)
|
51
|
+
```
|
52
|
+
|
53
|
+
#### in application
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
Rails.cache.fetch("key") do
|
57
|
+
"value"
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
42
61
|
## Contributing
|
43
62
|
|
44
63
|
1. Fork it ( http://github.com/hirocaster/double_write_cache_stores/fork )
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# monky patch
|
2
|
+
# support cas interface for ActiveSupport::Cache::DalliStore
|
3
|
+
module DalliStorePatch
|
4
|
+
def read_cas(name, options=nil)
|
5
|
+
options ||= {}
|
6
|
+
name = namespaced_key(name, options)
|
7
|
+
|
8
|
+
instrument(:get_cas, name) do |payload|
|
9
|
+
with { |c| c.get_cas(name) }
|
10
|
+
end
|
11
|
+
rescue Dalli::DalliError => e
|
12
|
+
logger.error("DalliError: #{e.message}") if logger
|
13
|
+
raise if raise_errors?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def write_cas(name, value, options=nil)
|
18
|
+
options ||= {}
|
19
|
+
name = namespaced_key(name, options)
|
20
|
+
expires_in = options[:expires_in]
|
21
|
+
|
22
|
+
instrument(:set_cas, name, value) do |payload|
|
23
|
+
cas = options.delete(:cas) || 0
|
24
|
+
expires_in = options.delete(:expires_in)
|
25
|
+
with { |c| c.set_cas(name, value, cas, expires_in, options) }
|
26
|
+
end
|
27
|
+
rescue Dalli::DalliError => e
|
28
|
+
logger.error("DalliError: #{e.message}") if logger
|
29
|
+
raise if raise_errors?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
begin
|
36
|
+
require "active_support"
|
37
|
+
require "active_support/cache/dalli_store"
|
38
|
+
|
39
|
+
ActiveSupport::Cache::DalliStore.send(:include, DalliStorePatch)
|
40
|
+
rescue => exception
|
41
|
+
end
|
@@ -17,12 +17,26 @@ class DoubleWriteCacheStores::Client
|
|
17
17
|
get_or_read_method_call key
|
18
18
|
end
|
19
19
|
|
20
|
+
def get_multi(*keys)
|
21
|
+
get_multi_or_read_multi_method_call *keys
|
22
|
+
end
|
23
|
+
|
20
24
|
def get_cas(key)
|
21
|
-
@read_and_write_store.get_cas
|
25
|
+
if @read_and_write_store.respond_to? :get_cas
|
26
|
+
@read_and_write_store.get_cas key
|
27
|
+
elsif @read_and_write_store.respond_to? :read_cas
|
28
|
+
@read_and_write_store.read_cas key
|
29
|
+
end
|
22
30
|
end
|
23
31
|
|
24
|
-
def set_cas(key, value, cas, options
|
25
|
-
cas_unique = @read_and_write_store.set_cas
|
32
|
+
def set_cas(key, value, cas=0, options=nil)
|
33
|
+
cas_unique = if @read_and_write_store.respond_to? :set_cas
|
34
|
+
@read_and_write_store.set_cas key, value, cas, options
|
35
|
+
elsif @read_and_write_store.respond_to? :read_cas
|
36
|
+
options ||= {}
|
37
|
+
options[:cas] = cas
|
38
|
+
@read_and_write_store.write_cas key, value, options
|
39
|
+
end
|
26
40
|
|
27
41
|
if @write_only_store && cas_unique
|
28
42
|
set_or_write_method_call @write_only_store, key, value, options
|
@@ -35,6 +49,10 @@ class DoubleWriteCacheStores::Client
|
|
35
49
|
get_or_read_method_call key
|
36
50
|
end
|
37
51
|
|
52
|
+
def read_multi(*keys)
|
53
|
+
get_multi_or_read_multi_method_call *keys
|
54
|
+
end
|
55
|
+
|
38
56
|
def delete(key)
|
39
57
|
@read_and_write_store.delete key
|
40
58
|
@write_only_store.delete key if @write_only_store
|
@@ -52,12 +70,16 @@ class DoubleWriteCacheStores::Client
|
|
52
70
|
write_cache_store key, value, options
|
53
71
|
end
|
54
72
|
|
55
|
-
def touch(key)
|
73
|
+
def touch(key, ttl=nil)
|
56
74
|
result = false
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
75
|
+
if defined?(Dalli) && @read_and_write_store.is_a?(Dalli::Client)
|
76
|
+
result = @read_and_write_store.touch key, ttl
|
77
|
+
else
|
78
|
+
read_and_write_backend = @read_and_write_store.instance_variable_get('@backend') || @read_and_write_store.instance_variable_get('@data')
|
79
|
+
if read_and_write_backend && read_and_write_backend.respond_to?(:touch)
|
80
|
+
result = read_and_write_backend.touch key, ttl
|
81
|
+
write_only_store_touch key, ttl
|
82
|
+
end
|
61
83
|
end
|
62
84
|
result
|
63
85
|
end
|
@@ -70,6 +92,33 @@ class DoubleWriteCacheStores::Client
|
|
70
92
|
end
|
71
93
|
end
|
72
94
|
|
95
|
+
def fetch(name, options = nil)
|
96
|
+
if @read_and_write_store.respond_to?(:fetch) ||
|
97
|
+
(@write_only_store && @write_only_store.respond_to?(:fetch))
|
98
|
+
if block_given?
|
99
|
+
result = @read_and_write_store.fetch(name, options = nil) { yield }
|
100
|
+
@write_only_store.fetch(name, options = nil) { yield } if @write_only_store
|
101
|
+
result
|
102
|
+
else
|
103
|
+
result = @read_and_write_store.fetch(name, options = nil)
|
104
|
+
@write_only_store.fetch(name, options = nil) if @write_only_store
|
105
|
+
result
|
106
|
+
end
|
107
|
+
else
|
108
|
+
raise UnSupportException.new "Unsupported #fetch from client object."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def increment(key, amount = 1, options = {})
|
113
|
+
increment_cache_store key, amount, options
|
114
|
+
end
|
115
|
+
alias_method :incr, :increment
|
116
|
+
|
117
|
+
def decrement(key, amount = 1, options = {})
|
118
|
+
decrement_cache_store key, amount, options
|
119
|
+
end
|
120
|
+
alias_method :decr, :decrement
|
121
|
+
|
73
122
|
private
|
74
123
|
|
75
124
|
def write_cache_store(key, value, options = nil)
|
@@ -79,7 +128,12 @@ class DoubleWriteCacheStores::Client
|
|
79
128
|
|
80
129
|
def set_or_write_method_call cache_store, key, value, options
|
81
130
|
if cache_store.respond_to? :set
|
82
|
-
|
131
|
+
if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
|
132
|
+
ttl = options[:expires_in] if options
|
133
|
+
cache_store.set key, value, ttl, options
|
134
|
+
else
|
135
|
+
cache_store.set key, value, options
|
136
|
+
end
|
83
137
|
elsif cache_store.respond_to? :write
|
84
138
|
cache_store.write key, value, options
|
85
139
|
end
|
@@ -93,6 +147,50 @@ class DoubleWriteCacheStores::Client
|
|
93
147
|
end
|
94
148
|
end
|
95
149
|
|
150
|
+
def get_multi_or_read_multi_method_call(*keys)
|
151
|
+
if @read_and_write_store.respond_to? :get_multi
|
152
|
+
@read_and_write_store.get_multi *keys
|
153
|
+
elsif @read_and_write_store.respond_to? :read_multi
|
154
|
+
@read_and_write_store.read_multi *keys
|
155
|
+
else
|
156
|
+
raise UnSupportException.new "Unsupported multi keys get or read from client object."
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def increment_cache_store(key, amount, options)
|
161
|
+
rw_store_value = incr_or_increment_method_call @read_and_write_store, key, amount, options
|
162
|
+
return rw_store_value unless @write_only_store
|
163
|
+
incr_or_increment_method_call @write_only_store, key, amount, options
|
164
|
+
end
|
165
|
+
|
166
|
+
def decrement_cache_store(key, amount, options)
|
167
|
+
rw_store_value = decr_or_decrement_method_call @read_and_write_store, key, amount, options
|
168
|
+
return rw_store_value unless @write_only_store
|
169
|
+
decr_or_decrement_method_call @write_only_store, key, amount, options
|
170
|
+
end
|
171
|
+
|
172
|
+
def incr_or_increment_method_call(cache_store, key, amount, options)
|
173
|
+
if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
|
174
|
+
ttl = options[:expires_in] if options
|
175
|
+
default = options.has_key?(:initial) ? options[:initial] : amount
|
176
|
+
cache_store.incr key, amount, ttl, default
|
177
|
+
elsif cache_store.respond_to? :increment
|
178
|
+
options[:initial] = amount unless options.has_key?(:initial)
|
179
|
+
cache_store.increment key, amount, options
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def decr_or_decrement_method_call(cache_store, key, amount, options)
|
184
|
+
if defined?(Dalli) && cache_store.is_a?(Dalli::Client)
|
185
|
+
ttl = options[:expires_in] if options
|
186
|
+
default = options.has_key?(:initial) ? options[:initial] : 0
|
187
|
+
cache_store.decr key, amount, ttl, default
|
188
|
+
elsif cache_store.respond_to? :decrement
|
189
|
+
options[:initial] = 0 unless options.has_key?(:initial)
|
190
|
+
cache_store.decrement key, amount, options
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
96
194
|
def flush_cache_store(method = :flush)
|
97
195
|
if @read_and_write_store.respond_to? method
|
98
196
|
if @write_only_store && @write_only_store.respond_to?(method)
|
@@ -104,11 +202,15 @@ class DoubleWriteCacheStores::Client
|
|
104
202
|
end
|
105
203
|
end
|
106
204
|
|
107
|
-
def write_only_store_touch(key)
|
205
|
+
def write_only_store_touch(key, ttl)
|
108
206
|
if @write_only_store
|
109
|
-
|
110
|
-
|
111
|
-
|
207
|
+
if defined?(Dalli) && @write_only_store.is_a?(Dalli::Client)
|
208
|
+
@write_only_store.touch key, ttl
|
209
|
+
else
|
210
|
+
write_only_backend = @write_only_store.instance_variable_get('@backend') || @write_only_store.instance_variable_get('@data')
|
211
|
+
if write_only_backend
|
212
|
+
write_only_backend.touch(key, ttl) if write_only_backend.respond_to?(:touch)
|
213
|
+
end
|
112
214
|
end
|
113
215
|
end
|
114
216
|
end
|
@@ -11,7 +11,7 @@ describe DoubleWriteCacheStores::Client do
|
|
11
11
|
|
12
12
|
describe '#initialize' do
|
13
13
|
it 'different cache store instance' do
|
14
|
-
expect{
|
14
|
+
expect{ DoubleWriteCacheStores::Client.new read_and_write_store, 'bad instance object' }.to raise_error RuntimeError
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -19,6 +19,10 @@ describe DoubleWriteCacheStores::Client do
|
|
19
19
|
DoubleWriteCacheStores::Client.new read_and_write_store, write_only_store
|
20
20
|
end
|
21
21
|
|
22
|
+
let :one_cache_store do
|
23
|
+
DoubleWriteCacheStores::Client.new read_and_write_store, nil
|
24
|
+
end
|
25
|
+
|
22
26
|
describe '#write' do
|
23
27
|
before do
|
24
28
|
copy_cache_store.write 'key', 'example-value', :expires_in => 1.day
|
@@ -29,181 +33,270 @@ describe DoubleWriteCacheStores::Client do
|
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
shared_examples "cache store example" do |cache_store|
|
37
|
+
describe '#read_multi' do
|
38
|
+
before do
|
39
|
+
cache_store.write 'key-a', 'example-value-a', :expires_in => 1.day
|
40
|
+
cache_store.write 'key-b', 'example-value-b', :expires_in => 1.day
|
41
|
+
end
|
38
42
|
|
39
|
-
|
40
|
-
before do
|
41
|
-
copy_cache_store.write 'will-delete-key', 'example-will-delete-value', :expires_in => 1.day
|
42
|
-
end
|
43
|
-
it 'delete key-value' do
|
44
|
-
expect(read_and_write_store.read 'will-delete-key').to eq 'example-will-delete-value'
|
45
|
-
expect(write_only_store.read 'will-delete-key').to eq 'example-will-delete-value'
|
43
|
+
after { cache_store.flush }
|
46
44
|
|
47
|
-
|
45
|
+
it 'get multi-keys values from multi store' do
|
46
|
+
results = cache_store.read_multi('key-a', 'key-b', 'key-c')
|
47
|
+
expect(results['key-a']).to eq 'example-value-a'
|
48
|
+
expect(results['key-b']).to eq 'example-value-b'
|
49
|
+
expect(results['key-c']).to eq nil
|
50
|
+
end
|
48
51
|
|
49
|
-
|
50
|
-
|
52
|
+
it 'returns values equal #get_multi' do
|
53
|
+
expect(cache_store.read_multi('key-a', 'key-b')).to eq cache_store.get_multi('key-a', 'key-b')
|
54
|
+
end
|
51
55
|
end
|
52
|
-
end
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
let :support_touch_read_and_write_store do
|
59
|
-
Padrino::Cache::Store::Memcache.new(::Dalli::Client.new('localhost:11211', options))
|
60
|
-
end
|
61
|
-
let :support_touch_write_only_store do
|
62
|
-
Padrino::Cache::Store::Memcache.new(::Dalli::Client.new('localhost:21211', options))
|
63
|
-
end
|
64
|
-
let :support_touch_copy_cache_store do
|
65
|
-
DoubleWriteCacheStores::Client.new support_touch_read_and_write_store, support_touch_write_only_store
|
66
|
-
end
|
67
|
-
before do
|
68
|
-
support_touch_copy_cache_store.set 'touch-key', 'touch-value', :expires_in => 1.day
|
69
|
-
end
|
57
|
+
describe '#fetch' do
|
58
|
+
before do
|
59
|
+
cache_store.write 'key-a', 'example-value-a', :expires_in => 1.day
|
60
|
+
end
|
70
61
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
expect(
|
62
|
+
after { cache_store.flush }
|
63
|
+
|
64
|
+
it 'returns value' do
|
65
|
+
expect(cache_store.fetch('key-a')).to eq 'example-value-a'
|
66
|
+
expect(cache_store.fetch('key-nil')).to eq nil
|
75
67
|
end
|
76
|
-
end
|
77
68
|
|
78
|
-
|
79
|
-
|
80
|
-
|
69
|
+
it 'get value and set value, block in args' do
|
70
|
+
expect(cache_store.fetch('key-b')).to eq nil
|
71
|
+
|
72
|
+
cache_store.fetch('key-b') do
|
73
|
+
'block-value-b'
|
74
|
+
end
|
75
|
+
|
76
|
+
expect(cache_store.fetch('key-b')).to eq 'block-value-b'
|
77
|
+
expect(cache_store.get('key-b')).to eq 'block-value-b'
|
78
|
+
|
79
|
+
result = cache_store.fetch('key-b') do
|
80
|
+
'not-overwrite-value'
|
81
|
+
end
|
82
|
+
expect(cache_store.fetch('key-b')).to eq 'block-value-b'
|
83
|
+
expect(cache_store.get('key-b')).to eq 'block-value-b'
|
81
84
|
end
|
85
|
+
end
|
82
86
|
|
87
|
+
describe '#delete' do
|
83
88
|
before do
|
84
|
-
|
89
|
+
copy_cache_store.write 'will-delete-key', 'example-will-delete-value', :expires_in => 1.day
|
85
90
|
end
|
91
|
+
it 'delete key-value' do
|
92
|
+
expect(read_and_write_store.read 'will-delete-key').to eq 'example-will-delete-value'
|
93
|
+
expect(write_only_store.read 'will-delete-key').to eq 'example-will-delete-value'
|
86
94
|
|
87
|
-
|
88
|
-
|
89
|
-
expect(
|
95
|
+
copy_cache_store.delete 'will-delete-key'
|
96
|
+
|
97
|
+
expect(read_and_write_store.read 'will-delete-key').to be_nil
|
98
|
+
expect(write_only_store.read 'will-delete-key').to be_nil
|
90
99
|
end
|
91
100
|
end
|
92
|
-
end
|
93
101
|
|
94
|
-
|
95
|
-
|
102
|
+
describe '#touch' do
|
103
|
+
let(:expire_ttl) { 1 }
|
104
|
+
|
96
105
|
before do
|
97
|
-
|
106
|
+
cache_store.set 'touch-key', 'touch-value', :expires_in => expire_ttl
|
98
107
|
end
|
99
|
-
|
100
|
-
|
108
|
+
|
109
|
+
it 'expired value, not touched' do
|
110
|
+
sleep expire_ttl
|
111
|
+
expect(cache_store.read 'touch-key').to eq nil
|
101
112
|
end
|
102
|
-
|
103
|
-
|
113
|
+
|
114
|
+
it 'expired value, touched expired' do
|
115
|
+
expect(cache_store.touch 'touch-key', expire_ttl).to be true
|
116
|
+
sleep expire_ttl
|
117
|
+
expect(cache_store.read 'touch-key').to eq nil
|
104
118
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
119
|
+
|
120
|
+
it 'returns value, before touched key' do
|
121
|
+
expect(cache_store.touch 'touch-key').to be true
|
122
|
+
sleep expire_ttl
|
123
|
+
expect(cache_store.read 'touch-key').to eq 'touch-value'
|
109
124
|
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#read' do
|
110
128
|
before do
|
111
|
-
|
129
|
+
cache_store.write 'key', 'example-read-value', :expires_in => 1.day
|
112
130
|
end
|
113
|
-
it '
|
114
|
-
expect(
|
115
|
-
|
131
|
+
it 'returns writed value' do
|
132
|
+
expect(cache_store.read 'key').to eq 'example-read-value'
|
133
|
+
end
|
134
|
+
it 'returns nil, not writed value' do
|
135
|
+
expect(cache_store.read 'not-set-key').to eq nil
|
116
136
|
end
|
117
137
|
end
|
118
|
-
end
|
119
138
|
|
120
|
-
|
121
|
-
context 'when not support flush method in cache store' do
|
139
|
+
describe '#flush' do
|
122
140
|
before do
|
123
141
|
copy_cache_store.write 'will-flush-key', 'will-flush-value', :expires_in => 1.day
|
124
142
|
end
|
125
143
|
it 'example' do
|
144
|
+
expect(copy_cache_store.read 'will-flush-key').to eq 'will-flush-value'
|
126
145
|
expect(copy_cache_store.flush).to eq true
|
127
|
-
expect(copy_cache_store.read 'will-flush-key').to
|
146
|
+
expect(copy_cache_store.read 'will-flush-key').to eq nil
|
128
147
|
end
|
129
148
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
let
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
149
|
+
|
150
|
+
shared_examples 'read cache after increment or decrement example' do
|
151
|
+
before { cache_store.set(key, 10, raw: true) }
|
152
|
+
it { expect((cache_store.read key).to_i).to eq expected_value }
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '#increment' do
|
156
|
+
let(:key) { 'key-increment' }
|
157
|
+
after { cache_store.flush }
|
158
|
+
|
159
|
+
it_behaves_like 'read cache after increment or decrement example' do
|
160
|
+
let!(:expected_value) { cache_store.increment key }
|
142
161
|
end
|
143
|
-
|
144
|
-
|
162
|
+
|
163
|
+
context 'when options[:initial] does not exist' do
|
164
|
+
context 'when value exists' do
|
165
|
+
before { cache_store.set(key, 0, raw: true) }
|
166
|
+
context 'when amount does not exist' do
|
167
|
+
it { expect(cache_store.increment key).to eq 1 }
|
168
|
+
end
|
169
|
+
context 'when amount exists' do
|
170
|
+
it { expect(cache_store.increment key, 2).to eq 2 }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
context 'when value does not exist' do
|
174
|
+
context 'when amount does not exist' do
|
175
|
+
it { expect(cache_store.increment key).to eq 1 }
|
176
|
+
end
|
177
|
+
context 'when amount exists' do
|
178
|
+
it { expect(cache_store.increment key, 2).to eq 2 }
|
179
|
+
end
|
180
|
+
end
|
145
181
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
182
|
+
|
183
|
+
context 'when options[:initial] exists' do
|
184
|
+
let(:opt) { { initial: 12345678 } }
|
185
|
+
context 'when value exists' do
|
186
|
+
before { cache_store.set(key, 0, raw: true) }
|
187
|
+
it { expect(cache_store.increment key, 1, opt).to eq 1 }
|
188
|
+
end
|
189
|
+
context 'when value does not exist' do
|
190
|
+
it { expect(cache_store.increment key, 1, opt).to eq opt[:initial] }
|
191
|
+
end
|
150
192
|
end
|
151
193
|
end
|
152
|
-
end
|
153
194
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
195
|
+
describe '#decrement' do
|
196
|
+
let(:key) { 'key-decrement' }
|
197
|
+
after { cache_store.flush }
|
198
|
+
|
199
|
+
it_behaves_like 'read cache after increment or decrement example' do
|
200
|
+
let!(:expected_value) { cache_store.decrement key }
|
160
201
|
end
|
161
202
|
|
162
|
-
|
163
|
-
|
203
|
+
context 'when options[:initial] does not exist' do
|
204
|
+
context 'when value exists' do
|
205
|
+
before { cache_store.set(key, 101, raw: true) }
|
206
|
+
context 'when amount does not exist' do
|
207
|
+
it { expect(cache_store.decrement key).to eq 100 }
|
208
|
+
end
|
209
|
+
context 'when amount exists' do
|
210
|
+
it { expect(cache_store.decrement key, 2).to eq 99 }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
context 'when value does not exist' do
|
214
|
+
context 'when amount does not exist' do
|
215
|
+
it { expect(cache_store.decrement key).to eq 0 }
|
216
|
+
end
|
217
|
+
context 'when amount exists' do
|
218
|
+
it { expect(cache_store.decrement key, 2).to eq 0 }
|
219
|
+
end
|
220
|
+
end
|
164
221
|
end
|
165
222
|
|
166
|
-
|
167
|
-
|
168
|
-
|
223
|
+
context 'when options[:initial] exists' do
|
224
|
+
let(:opt) { { initial: 12345678 } }
|
225
|
+
context 'when value exists' do
|
226
|
+
before { cache_store.set(key, 101, raw: true) }
|
227
|
+
it { expect(cache_store.decrement key, 1, opt).to eq 100 }
|
228
|
+
end
|
229
|
+
context 'when value does not exist' do
|
230
|
+
it { expect(cache_store.decrement key, 1, opt).to eq opt[:initial] }
|
231
|
+
end
|
169
232
|
end
|
170
233
|
end
|
171
234
|
|
172
|
-
|
173
|
-
|
174
|
-
|
235
|
+
describe '#[]=(key,value) and get #[](key)' do
|
236
|
+
it 'set value and get value' do
|
237
|
+
cache_store['key'] = 'example-value'
|
238
|
+
expect(cache_store['key']).to eq 'example-value'
|
175
239
|
end
|
240
|
+
end
|
176
241
|
|
177
|
-
|
178
|
-
|
242
|
+
describe 'cas' do
|
243
|
+
describe '#get_cas' do
|
244
|
+
before do
|
245
|
+
cache_store.set_cas 'get-cas-key', 'get-cas-value'
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'example' do
|
249
|
+
expect(cache_store.get_cas('get-cas-key')[0]).to eq 'get-cas-value'
|
250
|
+
expect(cache_store.get_cas('get-cas-key')[1]).to be_kind_of(Integer)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe '#set_cas' do
|
255
|
+
let :cas_unique do
|
256
|
+
cache_store.set_cas('set-cas-key', 'set-cas-value')
|
257
|
+
cache_store.get_cas('set-cas-key')[1]
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'example' do
|
261
|
+
expect(cache_store.set_cas('set-cas-key', 'set-cas-value', cas_unique)).to be_kind_of(Integer)
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'returns false, not set cache because different cas_unique' do
|
265
|
+
expect(cache_store.set_cas('set-cas-key', 'set-cas-value', cas_unique - 1)).to eq false
|
266
|
+
end
|
179
267
|
end
|
180
268
|
end
|
181
269
|
end
|
182
270
|
|
183
|
-
describe "
|
184
|
-
context "
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
support_set_cas_cache_store.set('cas-dalli-key', 'cas-value')
|
192
|
-
support_set_cas_cache_store.get_cas('cas-dalli-key')[1]
|
271
|
+
describe "shard example" do
|
272
|
+
context "ActiveSupport :dalli_store" do
|
273
|
+
read_and_write_store = ActiveSupport::Cache.lookup_store :dalli_store, 'localhost:11211'
|
274
|
+
write_only_store = ActiveSupport::Cache.lookup_store :dalli_store, 'localhost:21211'
|
275
|
+
|
276
|
+
context "double cache store" do
|
277
|
+
copy_cache_store = DoubleWriteCacheStores::Client.new(read_and_write_store, write_only_store)
|
278
|
+
it_behaves_like "cache store example", copy_cache_store
|
193
279
|
end
|
194
280
|
|
195
|
-
|
196
|
-
|
281
|
+
context "one cache store object" do
|
282
|
+
one_cache_store = DoubleWriteCacheStores::Client.new(read_and_write_store, nil)
|
283
|
+
it_behaves_like "cache store example", one_cache_store
|
197
284
|
end
|
198
285
|
end
|
199
286
|
|
200
|
-
context "
|
201
|
-
|
202
|
-
|
287
|
+
context "Dalli::Client" do
|
288
|
+
options = { :namespace => "app_v1", :compress => true }
|
289
|
+
read_and_write_store = Dalli::Client.new('localhost:11211', options)
|
290
|
+
write_only_store = Dalli::Client.new('localhost:21211', options)
|
291
|
+
|
292
|
+
context "double cache store" do
|
293
|
+
copy_cache_store = DoubleWriteCacheStores::Client.new(read_and_write_store, write_only_store)
|
294
|
+
it_behaves_like "cache store example", copy_cache_store
|
203
295
|
end
|
204
296
|
|
205
|
-
|
206
|
-
|
297
|
+
context "one cache store" do
|
298
|
+
one_cache_store = DoubleWriteCacheStores::Client.new(read_and_write_store)
|
299
|
+
it_behaves_like "cache store example", one_cache_store
|
207
300
|
end
|
208
301
|
end
|
209
302
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: double_write_cache_stores
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hirocaster
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -138,7 +138,9 @@ files:
|
|
138
138
|
- README.md
|
139
139
|
- Rakefile
|
140
140
|
- double_write_cache_stores.gemspec
|
141
|
+
- lib/dalli_store_patch.rb
|
141
142
|
- lib/double_write_cache_stores.rb
|
143
|
+
- lib/double_write_cache_stores/base_exception.rb
|
142
144
|
- lib/double_write_cache_stores/client.rb
|
143
145
|
- lib/double_write_cache_stores/version.rb
|
144
146
|
- spec/double_write_cache_stores/client_spec.rb
|
@@ -164,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
166
|
version: '0'
|
165
167
|
requirements: []
|
166
168
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.
|
169
|
+
rubygems_version: 2.4.5.1
|
168
170
|
signing_key:
|
169
171
|
specification_version: 4
|
170
172
|
summary: Double write cache stores wrapper.
|