dalli 2.7.2 → 3.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/{History.md → CHANGELOG.md} +231 -0
  3. data/Gemfile +14 -5
  4. data/LICENSE +1 -1
  5. data/README.md +33 -201
  6. data/lib/dalli/cas/client.rb +2 -57
  7. data/lib/dalli/client.rb +259 -254
  8. data/lib/dalli/compressor.rb +13 -2
  9. data/lib/dalli/key_manager.rb +121 -0
  10. data/lib/dalli/options.rb +7 -7
  11. data/lib/dalli/pid_cache.rb +40 -0
  12. data/lib/dalli/pipelined_getter.rb +177 -0
  13. data/lib/dalli/protocol/base.rb +239 -0
  14. data/lib/dalli/protocol/binary/request_formatter.rb +117 -0
  15. data/lib/dalli/protocol/binary/response_header.rb +36 -0
  16. data/lib/dalli/protocol/binary/response_processor.rb +239 -0
  17. data/lib/dalli/protocol/binary/sasl_authentication.rb +60 -0
  18. data/lib/dalli/protocol/binary.rb +173 -0
  19. data/lib/dalli/protocol/connection_manager.rb +254 -0
  20. data/lib/dalli/protocol/meta/key_regularizer.rb +31 -0
  21. data/lib/dalli/protocol/meta/request_formatter.rb +121 -0
  22. data/lib/dalli/protocol/meta/response_processor.rb +211 -0
  23. data/lib/dalli/protocol/meta.rb +178 -0
  24. data/lib/dalli/protocol/response_buffer.rb +54 -0
  25. data/lib/dalli/protocol/server_config_parser.rb +86 -0
  26. data/lib/dalli/protocol/ttl_sanitizer.rb +45 -0
  27. data/lib/dalli/protocol/value_compressor.rb +85 -0
  28. data/lib/dalli/protocol/value_marshaller.rb +59 -0
  29. data/lib/dalli/protocol/value_serializer.rb +91 -0
  30. data/lib/dalli/protocol.rb +8 -0
  31. data/lib/dalli/ring.rb +97 -86
  32. data/lib/dalli/server.rb +4 -694
  33. data/lib/dalli/servers_arg_normalizer.rb +54 -0
  34. data/lib/dalli/socket.rb +122 -80
  35. data/lib/dalli/version.rb +5 -1
  36. data/lib/dalli.rb +45 -14
  37. data/lib/rack/session/dalli.rb +162 -42
  38. metadata +40 -96
  39. data/Performance.md +0 -42
  40. data/Rakefile +0 -42
  41. data/dalli.gemspec +0 -29
  42. data/lib/action_dispatch/middleware/session/dalli_store.rb +0 -81
  43. data/lib/active_support/cache/dalli_store.rb +0 -363
  44. data/lib/dalli/railtie.rb +0 -7
  45. data/test/benchmark_test.rb +0 -242
  46. data/test/helper.rb +0 -55
  47. data/test/memcached_mock.rb +0 -121
  48. data/test/sasldb +0 -1
  49. data/test/test_active_support.rb +0 -439
  50. data/test/test_cas_client.rb +0 -107
  51. data/test/test_compressor.rb +0 -53
  52. data/test/test_dalli.rb +0 -625
  53. data/test/test_encoding.rb +0 -32
  54. data/test/test_failover.rb +0 -128
  55. data/test/test_network.rb +0 -54
  56. data/test/test_rack_session.rb +0 -341
  57. data/test/test_ring.rb +0 -85
  58. data/test/test_sasl.rb +0 -110
  59. data/test/test_serializer.rb +0 -30
  60. data/test/test_server.rb +0 -80
@@ -1,121 +0,0 @@
1
- require "socket"
2
-
3
- $started = {}
4
-
5
- module MemcachedMock
6
- def self.start(port=19123, &block)
7
- server = TCPServer.new("localhost", port)
8
- session = server.accept
9
- block.call session
10
- end
11
-
12
- def self.delayed_start(port=19123, wait=1, &block)
13
- server = TCPServer.new("localhost", port)
14
- sleep wait
15
- block.call server
16
- end
17
-
18
- module Helper
19
- # Forks the current process and starts a new mock Memcached server on
20
- # port 22122.
21
- #
22
- # memcached_mock(lambda {|sock| socket.write('123') }) do
23
- # assert_equal "PONG", Dalli::Client.new('localhost:22122').get('abc')
24
- # end
25
- #
26
- def memcached_mock(proc, meth = :start)
27
- return unless supports_fork?
28
- begin
29
- pid = fork do
30
- trap("TERM") { exit }
31
-
32
- MemcachedMock.send(meth) do |*args|
33
- proc.call(*args)
34
- end
35
- end
36
-
37
- sleep 0.3 # Give time for the socket to start listening.
38
- yield
39
- ensure
40
- if pid
41
- Process.kill("TERM", pid)
42
- Process.wait(pid)
43
- end
44
- end
45
- end
46
-
47
- PATHS = %w(
48
- /usr/local/bin/
49
- /opt/local/bin/
50
- /usr/bin/
51
- )
52
-
53
- def find_memcached
54
- output = `memcached -h | head -1`.strip
55
- if output && output =~ /^memcached (\d.\d.\d+)/ && $1 > '1.4'
56
- return (puts "Found #{output} in PATH"; '')
57
- end
58
- PATHS.each do |path|
59
- output = `memcached -h | head -1`.strip
60
- if output && output =~ /^memcached (\d\.\d\.\d+)/ && $1 > '1.4'
61
- return (puts "Found #{output} in #{path}"; path)
62
- end
63
- end
64
-
65
- raise Errno::ENOENT, "Unable to find memcached 1.4+ locally"
66
- end
67
-
68
- def memcached(port=19122, args='', options={})
69
- memcached_server(port, args)
70
- yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"], options)
71
- end
72
-
73
- def memcached_cas(port=19122, args='', options={})
74
- memcached_server(port, args)
75
- require 'dalli/cas/client'
76
- yield Dalli::Client.new(["localhost:#{port}", "127.0.0.1:#{port}"], options)
77
- end
78
-
79
- def memcached_server(port=19122, args='')
80
- Memcached.path ||= find_memcached
81
-
82
- cmd = "#{Memcached.path}memcached #{args} -p #{port}"
83
-
84
- $started[port] ||= begin
85
- #puts "Starting: #{cmd}..."
86
- pid = IO.popen(cmd).pid
87
- at_exit do
88
- begin
89
- Process.kill("TERM", pid)
90
- Process.wait(pid)
91
- rescue Errno::ECHILD, Errno::ESRCH
92
- end
93
- end
94
- sleep 0.1
95
- pid
96
- end
97
- end
98
-
99
- def supports_fork?
100
- !defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby'
101
- end
102
-
103
- def memcached_kill(port)
104
- pid = $started.delete(port)
105
- if pid
106
- begin
107
- Process.kill("TERM", pid)
108
- Process.wait(pid)
109
- rescue Errno::ECHILD, Errno::ESRCH
110
- end
111
- end
112
- end
113
-
114
- end
115
- end
116
-
117
- module Memcached
118
- class << self
119
- attr_accessor :path
120
- end
121
- end
data/test/sasldb DELETED
@@ -1 +0,0 @@
1
- testuser:testtest:::::::
@@ -1,439 +0,0 @@
1
- # encoding: utf-8
2
- require 'helper'
3
- require 'connection_pool'
4
-
5
- class MockUser
6
- def cache_key
7
- "users/1/21348793847982314"
8
- end
9
- end
10
-
11
- describe 'ActiveSupport' do
12
- describe 'active_support caching' do
13
-
14
- it 'has accessible options' do
15
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122', :expires_in => 5.minutes, :frob => 'baz')
16
- assert_equal 'baz', @dalli.options[:frob]
17
- end
18
-
19
- it 'allow mute and silence' do
20
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122')
21
- @dalli.mute do
22
- assert op_addset_succeeds(@dalli.write('foo', 'bar', nil))
23
- assert_equal 'bar', @dalli.read('foo', nil)
24
- end
25
- refute @dalli.silence?
26
- @dalli.silence!
27
- assert_equal true, @dalli.silence?
28
- end
29
-
30
- it 'handle nil options' do
31
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122')
32
- assert op_addset_succeeds(@dalli.write('foo', 'bar', nil))
33
- assert_equal 'bar', @dalli.read('foo', nil)
34
- assert_equal 18, @dalli.fetch('lkjsadlfk', nil) { 18 }
35
- assert_equal 18, @dalli.fetch('lkjsadlfk', nil) { 18 }
36
- assert_equal 1, @dalli.increment('lkjsa', 1, nil)
37
- assert_equal 2, @dalli.increment('lkjsa', 1, nil)
38
- assert_equal 1, @dalli.decrement('lkjsa', 1, nil)
39
- assert_equal true, @dalli.delete('lkjsa')
40
- end
41
-
42
- it 'support fetch' do
43
- with_activesupport do
44
- memcached do
45
- connect
46
- dvalue = @dalli.fetch('someotherkeywithoutspaces', :expires_in => 1.second) { 123 }
47
- assert_equal 123, dvalue
48
-
49
- o = Object.new
50
- o.instance_variable_set :@foo, 'bar'
51
- dvalue = @dalli.fetch(rand_key, :raw => true) { o }
52
- assert_equal o, dvalue
53
-
54
- dvalue = @dalli.fetch(rand_key) { o }
55
- assert_equal o, dvalue
56
-
57
- @dalli.write('false', false)
58
- dvalue = @dalli.fetch('false') { flunk }
59
- assert_equal false, dvalue
60
-
61
- user = MockUser.new
62
- @dalli.write(user.cache_key, false)
63
- dvalue = @dalli.fetch(user) { flunk }
64
- assert_equal false, dvalue
65
- end
66
- end
67
- end
68
-
69
- it 'support keys with spaces on Rails3' do
70
- with_activesupport do
71
- memcached do
72
- connect
73
- dvalue = @dalli.fetch('some key with spaces', :expires_in => 1.second) { 123 }
74
- assert_equal 123, dvalue
75
- end
76
- end
77
- end
78
-
79
- it 'support read_multi' do
80
- with_activesupport do
81
- memcached do
82
- connect
83
- x = rand_key
84
- y = rand_key
85
- assert_equal({}, @dalli.read_multi(x, y))
86
- @dalli.write(x, '123')
87
- @dalli.write(y, 123)
88
- assert_equal({ x => '123', y => 123 }, @dalli.read_multi(x, y))
89
- end
90
- end
91
- end
92
-
93
- it 'support read_multi with an array' do
94
- with_activesupport do
95
- memcached do
96
- connect
97
- x = rand_key
98
- y = rand_key
99
- assert_equal({}, @dalli.read_multi([x, y]))
100
- @dalli.write(x, '123')
101
- @dalli.write(y, 123)
102
- assert_equal({}, @dalli.read_multi([x, y]))
103
- @dalli.write([x, y], '123')
104
- assert_equal({ [x, y] => '123' }, @dalli.read_multi([x, y]))
105
- end
106
- end
107
- end
108
-
109
- it 'support raw read_multi' do
110
- with_activesupport do
111
- memcached do
112
- connect
113
- @dalli.write("abc", 5, :raw => true)
114
- @dalli.write("cba", 5, :raw => true)
115
- assert_equal({'abc' => '5', 'cba' => '5' }, @dalli.read_multi("abc", "cba"))
116
- end
117
- end
118
- end
119
-
120
- it 'support read_multi with LocalCache' do
121
- with_activesupport do
122
- memcached do
123
- connect
124
- x = rand_key
125
- y = rand_key
126
- assert_equal({}, @dalli.read_multi(x, y))
127
- @dalli.write(x, '123')
128
- @dalli.write(y, 456)
129
-
130
- @dalli.with_local_cache do
131
- assert_equal({ x => '123', y => 456 }, @dalli.read_multi(x, y))
132
- Dalli::Client.any_instance.expects(:get).with(any_parameters).never
133
-
134
- dres = @dalli.read(x)
135
- assert_equal dres, '123'
136
- end
137
-
138
- Dalli::Client.any_instance.unstub(:get)
139
-
140
- # Fresh LocalStore
141
- @dalli.with_local_cache do
142
- @dalli.read(x)
143
- Dalli::Client.any_instance.expects(:get_multi).with([y.to_s]).returns(y.to_s => 456)
144
-
145
- assert_equal({ x => '123', y => 456}, @dalli.read_multi(x, y))
146
- end
147
- end
148
- end
149
- end
150
-
151
- it 'supports fetch_multi' do
152
- with_activesupport do
153
- memcached do
154
- connect
155
-
156
- x = rand_key.to_s
157
- y = rand_key
158
- hash = { x => 'ABC', y => 'DEF' }
159
-
160
- @dalli.write(y, '123')
161
-
162
- results = @dalli.fetch_multi(x, y) { |key| hash[key] }
163
-
164
- assert_equal({ x => 'ABC', y => '123' }, results)
165
- assert_equal('ABC', @dalli.read(x))
166
- assert_equal('123', @dalli.read(y))
167
- end
168
- end
169
- end
170
-
171
- it 'support read, write and delete' do
172
- with_activesupport do
173
- memcached do
174
- connect
175
- y = rand_key
176
- assert_nil @dalli.read(y)
177
- dres = @dalli.write(y, 123)
178
- assert op_addset_succeeds(dres)
179
-
180
- dres = @dalli.read(y)
181
- assert_equal 123, dres
182
-
183
- dres = @dalli.delete(y)
184
- assert_equal true, dres
185
-
186
- user = MockUser.new
187
- dres = @dalli.write(user.cache_key, "foo")
188
- assert op_addset_succeeds(dres)
189
-
190
- dres = @dalli.read(user)
191
- assert_equal "foo", dres
192
-
193
- dres = @dalli.delete(user)
194
- assert_equal true, dres
195
-
196
- bigkey = '123456789012345678901234567890'
197
- @dalli.write(bigkey, 'double width')
198
- assert_equal 'double width', @dalli.read(bigkey)
199
- assert_equal({bigkey => "double width"}, @dalli.read_multi(bigkey))
200
- end
201
- end
202
- end
203
-
204
- it 'support read, write and delete with LocalCache' do
205
- with_activesupport do
206
- memcached do
207
- connect
208
- y = rand_key.to_s
209
- @dalli.with_local_cache do
210
- Dalli::Client.any_instance.expects(:get).with(y, {}).once.returns(123)
211
- dres = @dalli.read(y)
212
- assert_equal 123, dres
213
-
214
- Dalli::Client.any_instance.expects(:get).with(y, {}).never
215
-
216
- dres = @dalli.read(y)
217
- assert_equal 123, dres
218
-
219
- @dalli.write(y, 456)
220
- dres = @dalli.read(y)
221
- assert_equal 456, dres
222
-
223
- @dalli.delete(y)
224
- Dalli::Client.any_instance.expects(:get).with(y, {}).once.returns(nil)
225
- dres = @dalli.read(y)
226
- assert_equal nil, dres
227
- end
228
- end
229
- end
230
- end
231
-
232
- it 'support unless_exist with LocalCache' do
233
- with_activesupport do
234
- memcached do
235
- connect
236
- y = rand_key.to_s
237
- @dalli.with_local_cache do
238
- Dalli::Client.any_instance.expects(:add).with(y, 123, nil, {:unless_exist => true}).once.returns(true)
239
- dres = @dalli.write(y, 123, :unless_exist => true)
240
- assert_equal true, dres
241
-
242
- Dalli::Client.any_instance.expects(:add).with(y, 321, nil, {:unless_exist => true}).once.returns(false)
243
-
244
- dres = @dalli.write(y, 321, :unless_exist => true)
245
- assert_equal false, dres
246
-
247
- Dalli::Client.any_instance.expects(:get).with(y, {}).once.returns(123)
248
-
249
- dres = @dalli.read(y)
250
- assert_equal 123, dres
251
- end
252
- end
253
- end
254
- end
255
-
256
- it 'support increment/decrement commands' do
257
- with_activesupport do
258
- memcached do
259
- connect
260
- assert op_addset_succeeds(@dalli.write('counter', 0, :raw => true))
261
- assert_equal 1, @dalli.increment('counter')
262
- assert_equal 2, @dalli.increment('counter')
263
- assert_equal 1, @dalli.decrement('counter')
264
- assert_equal "1", @dalli.read('counter', :raw => true)
265
-
266
- assert_equal 1, @dalli.increment('counterX')
267
- assert_equal 2, @dalli.increment('counterX')
268
- assert_equal 2, @dalli.read('counterX', :raw => true).to_i
269
-
270
- assert_equal 5, @dalli.increment('counterY1', 1, :initial => 5)
271
- assert_equal 6, @dalli.increment('counterY1', 1, :initial => 5)
272
- assert_equal 6, @dalli.read('counterY1', :raw => true).to_i
273
-
274
- assert_equal nil, @dalli.increment('counterZ1', 1, :initial => nil)
275
- assert_equal nil, @dalli.read('counterZ1')
276
-
277
- assert_equal 5, @dalli.decrement('counterY2', 1, :initial => 5)
278
- assert_equal 4, @dalli.decrement('counterY2', 1, :initial => 5)
279
- assert_equal 4, @dalli.read('counterY2', :raw => true).to_i
280
-
281
- assert_equal nil, @dalli.decrement('counterZ2', 1, :initial => nil)
282
- assert_equal nil, @dalli.read('counterZ2')
283
-
284
- user = MockUser.new
285
- assert op_addset_succeeds(@dalli.write(user, 0, :raw => true))
286
- assert_equal 1, @dalli.increment(user)
287
- assert_equal 2, @dalli.increment(user)
288
- assert_equal 1, @dalli.decrement(user)
289
- assert_equal "1", @dalli.read(user, :raw => true)
290
- end
291
- end
292
- end
293
-
294
- it 'support exist command' do
295
- with_activesupport do
296
- memcached do
297
- connect
298
- @dalli.write(:foo, 'a')
299
- @dalli.write(:false_value, false)
300
-
301
- assert_equal true, @dalli.exist?(:foo)
302
- assert_equal true, @dalli.exist?(:false_value)
303
-
304
- assert_equal false, @dalli.exist?(:bar)
305
-
306
- user = MockUser.new
307
- @dalli.write(user, 'foo')
308
- assert_equal true, @dalli.exist?(user)
309
- end
310
- end
311
- end
312
-
313
- it 'support other esoteric commands' do
314
- with_activesupport do
315
- memcached do
316
- connect
317
- ds = @dalli.stats
318
- assert_equal 1, ds.keys.size
319
- assert ds[ds.keys.first].keys.size > 0
320
-
321
- @dalli.reset
322
- end
323
- end
324
- end
325
-
326
- it 'respect "raise_errors" option' do
327
- with_activesupport do
328
- memcached(29125) do
329
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:29125')
330
- @dalli.write 'foo', 'bar'
331
- assert_equal @dalli.read('foo'), 'bar'
332
-
333
- memcached_kill(29125)
334
-
335
- assert_equal @dalli.read('foo'), nil
336
-
337
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:29125', :raise_errors => true)
338
-
339
- exception = [Dalli::RingError, { :message => "No server available" }]
340
-
341
- assert_raises(*exception) { @dalli.read 'foo' }
342
- assert_raises(*exception) { @dalli.read 'foo', :raw => true }
343
- assert_raises(*exception) { @dalli.write 'foo', 'bar' }
344
- assert_raises(*exception) { @dalli.exist? 'foo' }
345
- assert_raises(*exception) { @dalli.increment 'foo' }
346
- assert_raises(*exception) { @dalli.decrement 'foo' }
347
- assert_raises(*exception) { @dalli.delete 'foo' }
348
- assert_equal @dalli.read_multi('foo', 'bar'), {}
349
- assert_raises(*exception) { @dalli.delete 'foo' }
350
- assert_raises(*exception) { @dalli.fetch('foo') { 42 } }
351
- end
352
- end
353
- end
354
- end
355
-
356
- it 'handle crazy characters from far-away lands' do
357
- with_activesupport do
358
- memcached do
359
- connect
360
- key = "fooƒ"
361
- value = 'bafƒ'
362
- assert op_addset_succeeds(@dalli.write(key, value))
363
- assert_equal value, @dalli.read(key)
364
- end
365
- end
366
- end
367
-
368
- it 'normalize options as expected' do
369
- with_activesupport do
370
- memcached do
371
- @dalli = ActiveSupport::Cache::DalliStore.new('localhost:19122', :expires_in => 1, :namespace => 'foo', :compress => true)
372
- assert_equal 1, @dalli.instance_variable_get(:@data).instance_variable_get(:@options)[:expires_in]
373
- assert_equal 'foo', @dalli.instance_variable_get(:@data).instance_variable_get(:@options)[:namespace]
374
- assert_equal ["localhost:19122"], @dalli.instance_variable_get(:@data).instance_variable_get(:@servers)
375
- end
376
- end
377
- end
378
-
379
- it 'handles nil server with additional options' do
380
- with_activesupport do
381
- memcached do
382
- @dalli = ActiveSupport::Cache::DalliStore.new(nil, :expires_in => 1, :namespace => 'foo', :compress => true)
383
- assert_equal 1, @dalli.instance_variable_get(:@data).instance_variable_get(:@options)[:expires_in]
384
- assert_equal 'foo', @dalli.instance_variable_get(:@data).instance_variable_get(:@options)[:namespace]
385
- assert_equal ["127.0.0.1:11211"], @dalli.instance_variable_get(:@data).instance_variable_get(:@servers)
386
- end
387
- end
388
- end
389
-
390
- it 'supports connection pooling' do
391
- with_activesupport do
392
- memcached do
393
- @dalli = ActiveSupport::Cache::DalliStore.new('localhost:19122', :expires_in => 1, :namespace => 'foo', :compress => true, :pool_size => 3)
394
- assert_equal nil, @dalli.read('foo')
395
- assert @dalli.write('foo', 1)
396
- assert_equal 1, @dalli.fetch('foo') { raise 'boom' }
397
- assert_equal true, @dalli.dalli.is_a?(ConnectionPool)
398
- assert_equal 1, @dalli.increment('bar')
399
- assert_equal 0, @dalli.decrement('bar')
400
- assert_equal true, @dalli.delete('bar')
401
- assert_equal [true], @dalli.clear
402
- assert_equal 1, @dalli.stats.size
403
- end
404
- end
405
- end
406
-
407
- it 'allow keys to be frozen' do
408
- with_activesupport do
409
- memcached do
410
- connect
411
- key = "foo"
412
- key.freeze
413
- assert op_addset_succeeds(@dalli.write(key, "value"))
414
- end
415
- end
416
- end
417
-
418
- it 'allow keys from a hash' do
419
- with_activesupport do
420
- memcached do
421
- connect
422
- map = { "one" => "one", "two" => "two" }
423
- map.each_pair do |k, v|
424
- assert op_addset_succeeds(@dalli.write(k, v))
425
- end
426
- assert_equal map, @dalli.read_multi(*(map.keys))
427
- end
428
- end
429
- end
430
-
431
- def connect
432
- @dalli = ActiveSupport::Cache.lookup_store(:dalli_store, 'localhost:19122', :expires_in => 10.seconds, :namespace => lambda{33.to_s(36)})
433
- @dalli.clear
434
- end
435
-
436
- def rand_key
437
- rand(1_000_000_000)
438
- end
439
- end
@@ -1,107 +0,0 @@
1
- require 'helper'
2
- require 'memcached_mock'
3
-
4
- describe 'Dalli::Cas::Client' do
5
- describe 'using a live server' do
6
- it 'supports get with CAS' do
7
- memcached_cas do |dc|
8
- dc.flush
9
-
10
- expected = { 'blah' => 'blerg!' }
11
- get_block_called = false
12
- stored_value = stored_cas = nil
13
- # Validate call-with-block
14
- dc.get_cas('gets_key') do |v, cas|
15
- get_block_called = true
16
- stored_value = v
17
- stored_cas = cas
18
- end
19
- assert get_block_called
20
- assert_nil stored_value
21
-
22
- dc.set('gets_key', expected)
23
-
24
- # Validate call-with-return-value
25
- stored_value, stored_cas = dc.get_cas('gets_key')
26
- assert_equal stored_value, expected
27
- assert(stored_cas != 0)
28
- end
29
- end
30
-
31
- it 'supports multi-get with CAS' do
32
- memcached_cas do |dc|
33
- dc.close
34
- dc.flush
35
-
36
- expected_hash = {'a' => 'foo', 'b' => 123}
37
- expected_hash.each_pair do |k, v|
38
- dc.set(k, v)
39
- end
40
-
41
- # Invocation without block
42
- resp = dc.get_multi_cas(%w(a b c d e f))
43
- resp.each_pair do |k, data|
44
- value, cas = [data.first, data.second]
45
- assert_equal expected_hash[k], value
46
- assert(cas && cas != 0)
47
- end
48
-
49
- # Invocation with block
50
- dc.get_multi_cas(%w(a b c d e f)) do |k, data|
51
- value, cas = [data.first, data.second]
52
- assert_equal expected_hash[k], value
53
- assert(cas && cas != 0)
54
- end
55
- end
56
- end
57
-
58
- it 'supports replace-with-CAS operation' do
59
- memcached_cas do |dc|
60
- dc.flush
61
- cas = dc.set('key', 'value')
62
-
63
- # Accepts CAS, replaces, and returns new CAS
64
- cas = dc.replace_cas('key', 'value2', cas)
65
- assert cas.is_a?(Integer)
66
-
67
- assert_equal 'value2', dc.get('key')
68
- end
69
- end
70
-
71
- it 'supports delete with CAS' do
72
- memcached_cas do |dc|
73
- cas = dc.set('some_key', 'some_value')
74
- dc.delete_cas('some_key', cas)
75
- assert_nil dc.get('some_key')
76
- end
77
- end
78
-
79
- it 'handles CAS round-trip operations' do
80
- memcached_cas do |dc|
81
- dc.flush
82
-
83
- expected = {'blah' => 'blerg!'}
84
- dc.set('some_key', expected)
85
-
86
- value, cas = dc.get_cas('some_key')
87
- assert_equal value, expected
88
- assert(!cas.nil? && cas != 0)
89
-
90
- # Set operation, first with wrong then with correct CAS
91
- expected = {'blah' => 'set succeeded'}
92
- assert(dc.set_cas('some_key', expected, cas+1) == false)
93
- assert op_addset_succeeds(cas = dc.set_cas('some_key', expected, cas))
94
-
95
- # Replace operation, first with wrong then with correct CAS
96
- expected = {'blah' => 'replace succeeded'}
97
- assert(dc.replace_cas('some_key', expected, cas+1) == false)
98
- assert op_addset_succeeds(cas = dc.replace_cas('some_key', expected, cas))
99
-
100
- # Delete operation, first with wrong then with correct CAS
101
- assert(dc.delete_cas('some_key', cas+1) == false)
102
- assert dc.delete_cas('some_key', cas)
103
- end
104
- end
105
-
106
- end
107
- end