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 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.