double_write_cache_stores 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5dbec8739b2952e40813ae8355317815e4ac6769
4
- data.tar.gz: 7f17258222ba0e1211ee777e69193def91723fc4
3
+ metadata.gz: 2f2e06c115f9f6f2c93e70bd217a9f0d2277e4b8
4
+ data.tar.gz: 026266132650bcfe4a9b11f8a7ea78cbaeaaceeb
5
5
  SHA512:
6
- metadata.gz: 1c84a1e5255940a10299a068298666a82138f99e9623d737256f20f572bc6f792be8bc90ea5a93ac2fc8eef76ed0b1e1fdfd778fb865e08e3d1d186b1ef6d3c8
7
- data.tar.gz: bc644b50386794570dc390a7e40af9bc4a86e6bb1f527df621a7da213f89bb8d6936714f2deecf1c423b42d9b58c242c58de9dabb64e8d06f295e810ed908fd0
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
@@ -1,4 +1,6 @@
1
1
  require "double_write_cache_stores/version"
2
2
  require "double_write_cache_stores/client"
3
+ require "double_write_cache_stores/base_exception"
4
+ require "dalli_store_patch"
3
5
  module DoubleWriteCacheStores
4
6
  end
@@ -0,0 +1,4 @@
1
+ module DoubleWriteCacheStores
2
+ class BaseException < StandardError; end
3
+ class UnSupportException < StandardError; end
4
+ 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 key
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 = nil)
25
- cas_unique = @read_and_write_store.set_cas key, value, cas, options
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
- read_and_write_backend = @read_and_write_store.instance_variable_get('@backend') || @read_and_write_store.instance_variable_get('@data')
58
- if read_and_write_backend && read_and_write_backend.respond_to?(:touch)
59
- result = read_and_write_backend.touch key
60
- write_only_store_touch key
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
- cache_store.set key, value, options
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
- write_only_backend = @write_only_store.instance_variable_get('@backend') || @write_only_store.instance_variable_get('@data')
110
- if write_only_backend
111
- write_only_backend.touch key if write_only_backend.respond_to?(:touch)
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
@@ -1,3 +1,3 @@
1
1
  module DoubleWriteCacheStores
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  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{ subject.new read_and_write_store, 'bad instance object' }.to raise_error
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
- describe 'set #[]=(key, value) and get #[](key)' do
33
- it 'set value and get value' do
34
- copy_cache_store['key'] = 'example-value'
35
- expect(copy_cache_store['key']).to eq 'example-value'
36
- end
37
- end
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
- describe '#delete' do
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
- copy_cache_store.delete 'will-delete-key'
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
- expect(read_and_write_store.read 'will-delete-key').to be_nil
50
- expect(write_only_store.read 'will-delete-key').to be_nil
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
- describe '#touch' do
55
- let :options do
56
- { :namespace => "app_v1", :compress => true }
57
- end
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
- context 'Dalli::Client' do
72
- it 'example' do
73
- expect(support_touch_copy_cache_store.touch 'touch-key').to be true
74
- expect(support_touch_copy_cache_store.touch 'non-set-key').to be nil
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
- context 'ActiveSupport::Cache::DalliStore' do
79
- let :double_write_dalli_store do
80
- DoubleWriteCacheStores::Client.new ActiveSupport::Cache::DalliStore.new('localhost:11211', options), ActiveSupport::Cache::DalliStore.new('localhost:21211', options)
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
- double_write_dalli_store.set 'touch-key', 'touch-valule', :expires_in => 1.day
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
- it 'example' do
88
- expect(double_write_dalli_store.touch 'touch-key').to be true
89
- expect(double_write_dalli_store.touch 'non-set-key').to be nil
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
- describe '#read' do
95
- context 'when standard case' do
102
+ describe '#touch' do
103
+ let(:expire_ttl) { 1 }
104
+
96
105
  before do
97
- copy_cache_store.write 'key', 'example-read-value', :expires_in => 1.day
106
+ cache_store.set 'touch-key', 'touch-value', :expires_in => expire_ttl
98
107
  end
99
- it 'get read key value from multi store' do
100
- expect(copy_cache_store.read 'key').to eq 'example-read-value'
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
- it 'not get no set key-value' do
103
- expect(copy_cache_store.read 'not-set-key').to be_nil
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
- end
106
- context 'when not set copy cache store' do
107
- let :not_copy_cache_store do
108
- DoubleWriteCacheStores::Client.new read_and_write_store
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
- not_copy_cache_store.write 'no-copy-key', 'example-read-value', :expires_in => 1.day
129
+ cache_store.write 'key', 'example-read-value', :expires_in => 1.day
112
130
  end
113
- it 'not sync cache store' do
114
- expect(read_and_write_store.read 'no-copy-key').to eq 'example-read-value'
115
- expect(write_only_store.read 'no-copy-key').to be_nil
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
- describe '#flush' do
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 be_nil
146
+ expect(copy_cache_store.read 'will-flush-key').to eq nil
128
147
  end
129
148
  end
130
- context 'when support flush method in backend cache store' do
131
- let :options do
132
- { :namespace => "app_v1", :compress => true }
133
- end
134
- let :support_flash_read_and_write_store do
135
- Padrino::Cache::Store::Memcache.new(::Dalli::Client.new('localhost:11211', options))
136
- end
137
- let :support_flash_write_only_store do
138
- Padrino::Cache::Store::Memcache.new(::Dalli::Client.new('localhost:21211', options))
139
- end
140
- let :support_flash_copy_cache_store do
141
- DoubleWriteCacheStores::Client.new support_flash_read_and_write_store, support_flash_write_only_store
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
- before do
144
- support_flash_copy_cache_store.set 'will-flush-key', 'will-flush-value', :expires_in => 1.day
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
- it 'example' do
147
- expect(support_flash_copy_cache_store.get 'will-flush-key').to eq 'will-flush-value'
148
- expect(support_flash_copy_cache_store.flush).to be true
149
- expect(support_flash_copy_cache_store.get 'will-flush-key').to be_nil
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
- describe "#get_cas" do
155
- context "when support get_cas method in backend cache store" do
156
- let :support_get_cas_cache_store do
157
- read_and_write = ::Dalli::Client.new(['localhost:11211'])
158
- write_only = ::Dalli::Client.new(['localhost:21211'])
159
- DoubleWriteCacheStores::Client.new read_and_write, write_only
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
- before do
163
- support_get_cas_cache_store.set 'cas-dalli-key', 'cas-dalli-value'
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
- it 'example' do
167
- expect(support_get_cas_cache_store.get_cas('cas-dalli-key')[0]).to eq 'cas-dalli-value'
168
- expect(support_get_cas_cache_store.get_cas('cas-dalli-key')[1]).to be_kind_of(Integer)
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
- context "when doesn't support get_cas method in backend cache store" do
173
- let :not_support_get_cas_cache_store do
174
- DoubleWriteCacheStores::Client.new ActiveSupport::Cache::DalliStore.new('localhost:11211'), ActiveSupport::Cache::DalliStore.new('localhost:21211')
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
- it 'should raise NoMethodError' do
178
- expect{ not_support_get_cas_cache_store.get_cas 'cas-key' }.to raise_error(NoMethodError)
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 "#set_cas" do
184
- context "when support set_cas method in backend cache store" do
185
- let :support_set_cas_cache_store do
186
- read_and_write = ::Dalli::Client.new(['localhost:11211'])
187
- write_only = ::Dalli::Client.new(['localhost:21211'])
188
- DoubleWriteCacheStores::Client.new read_and_write, write_only
189
- end
190
- let :cas_unique do
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
- it 'example' do
196
- expect(support_set_cas_cache_store.set_cas('cas-dalli-key', 'cas-dalli-value', cas_unique)).to be_kind_of(Integer)
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 "when doesn't support set_cas method in backend cache store" do
201
- let :not_support_set_cas_cache_store do
202
- DoubleWriteCacheStores::Client.new ActiveSupport::Cache::DalliStore.new('localhost:11211'), ActiveSupport::Cache::DalliStore.new('localhost:21211')
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
- it 'should raise NoMethodError' do
206
- expect{ not_support_set_cas_cache_store.set_cas('cas-key', 'cas-value', 1) }.to raise_error(NoMethodError)
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
@@ -2,6 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe DoubleWriteCacheStores do
4
4
  it 'should have a version number' do
5
- DoubleWriteCacheStores::VERSION.should_not be_nil
5
+ expect(DoubleWriteCacheStores::VERSION).not_to be_nil
6
6
  end
7
7
  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.2.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-07-09 00:00:00.000000000 Z
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.2.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.