dalli 1.1.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dalli might be problematic. Click here for more details.

data/test/test_dalli.rb CHANGED
@@ -2,6 +2,33 @@ require 'helper'
2
2
  require 'memcached_mock'
3
3
 
4
4
  describe 'Dalli' do
5
+ describe 'options parsing' do
6
+ should 'handle deprecated options' do
7
+ dc = Dalli::Client.new('foo', :compression => true)
8
+ assert dc.instance_variable_get(:@options)[:compress]
9
+ end
10
+ end
11
+
12
+ describe 'key validation' do
13
+ should 'not allow whitespace' do
14
+ dc = Dalli::Client.new
15
+ assert_raises ArgumentError do
16
+ dc.set ' ', 1
17
+ end
18
+ assert_raises ArgumentError do
19
+ dc.set "\t", 1
20
+ end
21
+ assert_raises ArgumentError do
22
+ dc.set "\n", 1
23
+ end
24
+ assert_raises ArgumentError do
25
+ dc.set "", 1
26
+ end
27
+ assert_raises ArgumentError do
28
+ dc.set nil, 1
29
+ end
30
+ end
31
+ end
5
32
 
6
33
  should "default to localhost:11211" do
7
34
  dc = Dalli::Client.new
@@ -26,60 +53,6 @@ describe 'Dalli' do
26
53
  assert_equal s2, s3
27
54
  end
28
55
 
29
- context 'using unix sockets' do
30
- should 'pass smoke test' do
31
- memcached(nil,'',{:unix => true}) do |dc|
32
- # get/set
33
- dc.flush
34
- assert_nil dc.get(:a)
35
- assert dc.set(:a,1)
36
- assert_equal 1, dc.get(:a)
37
-
38
- # replace
39
- dc.set(:a,1)
40
- dc.replace(:a,2)
41
- assert_equal 2, dc.get(:a)
42
-
43
- # delete
44
- dc.delete(:a)
45
- assert_nil dc.get(:a)
46
-
47
- # fetch
48
- executed, expected = false, 1
49
-
50
- value = dc.fetch(:fetched) do
51
- executed = true
52
- expected
53
- end
54
-
55
- assert executed
56
- assert_equal expected, value
57
-
58
- executed = false
59
- value = dc.fetch(:fetched) do
60
- executed = true
61
- expected
62
- end
63
-
64
- assert !executed
65
- assert_equal expected, value
66
-
67
- # cas
68
- dc.set(:a,1)
69
- 3.times { dc.cas(:a){|a| a+=1} }
70
- assert_equal 4, dc.get(:a)
71
-
72
- # get_multi
73
- resp = dc.get_multi(%w(b c d))
74
- assert_equal({}, resp)
75
- dc.set("b",1)
76
- dc.set("c",11)
77
- resp = dc.get_multi(%w(b c d))
78
- assert_equal({"b" => 1, "c" => 11}, resp)
79
- end
80
- end
81
- end
82
-
83
56
  context 'using a live server' do
84
57
 
85
58
  should "support get/set" do
@@ -103,6 +76,30 @@ describe 'Dalli' do
103
76
  end
104
77
  end
105
78
 
79
+ should "support stats" do
80
+ memcached do |dc|
81
+ # make sure that get_hits would not equal 0
82
+ dc.get(:a)
83
+
84
+ stats = dc.stats
85
+ servers = stats.keys
86
+ assert(servers.any? do |s|
87
+ stats[s]["get_hits"].to_i != 0
88
+ end)
89
+
90
+ # reset_stats test
91
+ results = dc.reset_stats
92
+ assert(results.all? { |x| x })
93
+ stats = dc.stats
94
+ servers = stats.keys
95
+
96
+ # check if reset was performed
97
+ servers.each do |s|
98
+ assert_equal 0, dc.stats[s]["get_hits"].to_i
99
+ end
100
+ end
101
+ end
102
+
106
103
  should "support the fetch operation" do
107
104
  memcached do |dc|
108
105
  dc.flush
@@ -270,6 +267,20 @@ describe 'Dalli' do
270
267
  end
271
268
  end
272
269
 
270
+ should 'allow TCP connections to be configured for keepalive' do
271
+ memcached(19122, '', :keepalive => true) do |dc|
272
+ dc.set(:a, 1)
273
+ ring = dc.send(:ring)
274
+ server = ring.servers.first
275
+ socket = server.instance_variable_get('@sock')
276
+
277
+ optval = socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE)
278
+ optval = optval.unpack 'i'
279
+
280
+ assert_equal true, (optval[0] != 0)
281
+ end
282
+ end
283
+
273
284
  should "pass a simple smoke test" do
274
285
  memcached do |dc|
275
286
  resp = dc.flush
@@ -396,7 +407,7 @@ describe 'Dalli' do
396
407
  context 'with compression' do
397
408
  should 'allow large values' do
398
409
  memcached do |dc|
399
- dalli = Dalli::Client.new(dc.instance_variable_get(:@servers), :compression => true)
410
+ dalli = Dalli::Client.new(dc.instance_variable_get(:@servers), :compress => true)
400
411
 
401
412
  value = "0"*1024*1024
402
413
  assert_raises Dalli::DalliError, /too large/ do
@@ -428,7 +439,7 @@ describe 'Dalli' do
428
439
 
429
440
  should 'fit more values with compression' do
430
441
  memcached(19126, '-m 1 -M') do |dc|
431
- dalli = Dalli::Client.new('localhost:19126', :compression => true)
442
+ dalli = Dalli::Client.new('localhost:19126', :compress => true)
432
443
  failed = false
433
444
  value = "1234567890"*1000
434
445
  10_000.times do |idx|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dalli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.5
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-25 00:00:00.000000000 Z
12
+ date: 2012-03-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mini_shoulda
16
- requirement: &70232123468080 !ruby/object:Gem::Requirement
16
+ requirement: &70227367207220 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70232123468080
24
+ version_requirements: *70227367207220
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mocha
27
- requirement: &70232123467180 !ruby/object:Gem::Requirement
27
+ requirement: &70227367204000 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,29 +32,18 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70232123467180
35
+ version_requirements: *70227367204000
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &70232123465920 !ruby/object:Gem::Requirement
38
+ requirement: &70227367199700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: '3.0'
44
- type: :development
45
- prerelease: false
46
- version_requirements: *70232123465920
47
- - !ruby/object:Gem::Dependency
48
- name: memcache-client
49
- requirement: &70232123465100 !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
52
- - - ! '>='
41
+ - - ~>
53
42
  - !ruby/object:Gem::Version
54
- version: 1.8.5
43
+ version: '3'
55
44
  type: :development
56
45
  prerelease: false
57
- version_requirements: *70232123465100
46
+ version_requirements: *70227367199700
58
47
  description: High performance memcached client for Ruby
59
48
  email: mperham@gmail.com
60
49
  executables: []
@@ -63,10 +52,7 @@ extra_rdoc_files: []
63
52
  files:
64
53
  - lib/action_dispatch/middleware/session/dalli_store.rb
65
54
  - lib/active_support/cache/dalli_store.rb
66
- - lib/active_support/cache/dalli_store23.rb
67
55
  - lib/dalli/client.rb
68
- - lib/dalli/compatibility.rb
69
- - lib/dalli/memcache-client.rb
70
56
  - lib/dalli/options.rb
71
57
  - lib/dalli/ring.rb
72
58
  - lib/dalli/server.rb
@@ -81,13 +67,11 @@ files:
81
67
  - Gemfile
82
68
  - dalli.gemspec
83
69
  - Performance.md
84
- - Upgrade.md
85
70
  - test/abstract_unit.rb
86
71
  - test/benchmark_test.rb
87
72
  - test/helper.rb
88
73
  - test/memcached_mock.rb
89
74
  - test/test_active_support.rb
90
- - test/test_compatibility.rb
91
75
  - test/test_dalli.rb
92
76
  - test/test_encoding.rb
93
77
  - test/test_failover.rb
@@ -95,7 +79,6 @@ files:
95
79
  - test/test_ring.rb
96
80
  - test/test_sasl.rb
97
81
  - test/test_session_store.rb
98
- - test/test_synchrony.rb
99
82
  homepage: http://github.com/mperham/dalli
100
83
  licenses: []
101
84
  post_install_message:
@@ -127,7 +110,6 @@ test_files:
127
110
  - test/helper.rb
128
111
  - test/memcached_mock.rb
129
112
  - test/test_active_support.rb
130
- - test/test_compatibility.rb
131
113
  - test/test_dalli.rb
132
114
  - test/test_encoding.rb
133
115
  - test/test_failover.rb
@@ -135,4 +117,3 @@ test_files:
135
117
  - test/test_ring.rb
136
118
  - test/test_sasl.rb
137
119
  - test/test_session_store.rb
138
- - test/test_synchrony.rb
data/Upgrade.md DELETED
@@ -1,45 +0,0 @@
1
- Upgrading from memcache-client
2
- ========
3
-
4
- Dalli is not meant to be 100% compatible with memcache-client, there are a few minor differences in the API.
5
-
6
-
7
- Compatibility Layer
8
- ----------------------
9
-
10
- Enable memcache-client compatibility in your application when upgrading by requiring this when
11
- initalizing your app:
12
-
13
- require 'dalli/memcache-client'
14
-
15
- This will print out warnings if your code is using the old memcache-client API style, explained below.
16
-
17
-
18
- Marshalling
19
- ---------------
20
-
21
- Dalli has changed the raw parameter to a :raw option. The memcache-client API allowed you to control marshalling on a per-method basis using a boolean 'raw' parameter to several of the API methods:
22
-
23
- cache = MemCache.new
24
- cache.set('abc', 123, 0, true)
25
- cache.get('abc', true) => '123'
26
-
27
- cache.set('abc', 123, 0)
28
- cache.get('abc') => 123
29
-
30
- Note that the last parameter is set to true in the first two API calls and so `get` returns a string, not an integer. In the second example, we don't provide the raw parameter. Since it defaults to false, it works exactly like Dalli.
31
-
32
- If the code specifies raw as false, you can simply remove that parameter. If the code is using raw = true, you will need to use the :raw option:
33
-
34
- cache.set('abc', 123, 0, :raw => true)
35
-
36
-
37
- Return Values
38
- ----------------
39
-
40
- In memcache-client, `set(key, value)` normally returns "STORED\r\n". This is an artifact of the text protocol used in earlier versions of memcached. Code that checks the return value will need to be updated. Dalli raises errors for exceptional cases but otherwise returns true or false depending on whether the operation succeeded or not. These methods are affected:
41
-
42
- set
43
- add
44
- replace
45
- delete
@@ -1,172 +0,0 @@
1
- begin
2
- require 'dalli'
3
- rescue LoadError => e
4
- $stderr.puts "You don't have dalli installed in your application: #{e.message}"
5
- raise e
6
- end
7
- require 'digest/md5'
8
-
9
- module ActiveSupport
10
- module Cache
11
- # A cache store implementation which stores data in Memcached:
12
- # http://www.danga.com/memcached/
13
- #
14
- # DalliStore implements the Strategy::LocalCache strategy which implements
15
- # an in memory cache inside of a block.
16
- class DalliStore < Store
17
-
18
- def self.build_mem_cache(*addresses)
19
- addresses = addresses.flatten
20
- options = addresses.extract_options!
21
- addresses = ["localhost"] if addresses.empty?
22
- Dalli::Client.new(addresses, options)
23
- end
24
-
25
- # Creates a new DalliStore object, with the given memcached server
26
- # addresses. Each address is either a host name, or a host-with-port string
27
- # in the form of "host_name:port". For example:
28
- #
29
- # ActiveSupport::Cache::DalliStore.new("localhost", "server-downstairs.localnetwork:8229")
30
- #
31
- # If no addresses are specified, then DalliStore will connect to
32
- # localhost port 11211 (the default memcached port).
33
- #
34
- def initialize(*addresses)
35
- addresses = addresses.flatten
36
- options = addresses.extract_options!
37
-
38
- mem_cache_options = options.dup
39
- @namespace = mem_cache_options.delete(:namespace)
40
- @expires_in = mem_cache_options[:expires_in]
41
- @data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
42
-
43
- extend Strategy::LocalCache
44
- end
45
-
46
- # Reads multiple keys from the cache using a single call to the
47
- # servers for all keys. Options can be passed in the last argument.
48
- def read_multi(*names)
49
- options = nil
50
- options = names.pop if names.last.is_a?(Hash)
51
- keys_to_names = names.inject({}){|map, name| map[escape_key(name)] = name; map}
52
- cache_keys = {}
53
- # map keys to servers
54
- names.each do |key|
55
- cache_key = escape_key key
56
- cache_keys[cache_key] = key
57
- end
58
-
59
- values = @data.get_multi(keys_to_names.keys, options)
60
- results = {}
61
- values.each do |key, value|
62
- results[cache_keys[key]] = value
63
- end
64
- results
65
- end
66
-
67
- def reset
68
- @data.reset
69
- end
70
-
71
- # Read an entry from the cache.
72
- def read(key, options = nil) # :nodoc:
73
- super
74
- @data.get(escape_key(key), options)
75
- rescue Dalli::DalliError => e
76
- logger.error("DalliError: #{e.message}")
77
- nil
78
- end
79
-
80
- # Writes a value to the cache.
81
- #
82
- # Possible options:
83
- # - +:unless_exist+ - set to true if you don't want to update the cache
84
- # if the key is already set.
85
- # - +:expires_in+ - the number of seconds that this value may stay in
86
- # the cache. See ActiveSupport::Cache::Store#write for an example.
87
- def write(key, value, options = nil)
88
- super
89
- value = value.to_s if options && options[:raw]
90
- method = options && options[:unless_exist] ? :add : :set
91
- @data.send(method, escape_key(key), value, expires_in(options), options)
92
- rescue Dalli::DalliError => e
93
- logger.error("DalliError: #{e.message}")
94
- false
95
- end
96
-
97
- def delete(key, options = nil) # :nodoc:
98
- super
99
- @data.delete(escape_key(key))
100
- rescue Dalli::DalliError => e
101
- logger.error("DalliError: #{e.message}")
102
- false
103
- end
104
-
105
- def exist?(key, options = nil) # :nodoc:
106
- # Doesn't call super, cause exist? in memcache is in fact a read
107
- # But who cares? Reading is very fast anyway
108
- # Local cache is checked first, if it doesn't know then memcache itself is read from
109
- !read(key, options).nil?
110
- end
111
-
112
- # Increment a cached value. This method uses the memcached incr atomic
113
- # operator and can only be used on values written with the :raw option.
114
- # Calling it on a value not stored with :raw will initialize that value
115
- # to zero.
116
- def increment(key, amount = 1) # :nodoc:
117
- log("incrementing", key, amount)
118
- @data.incr(escape_key(key), amount)
119
- rescue Dalli::DalliError => e
120
- logger.error("DalliError: #{e.message}") if logger
121
- nil
122
- end
123
-
124
- # Decrement a cached value. This method uses the memcached decr atomic
125
- # operator and can only be used on values written with the :raw option.
126
- # Calling it on a value not stored with :raw will initialize that value
127
- # to zero.
128
- def decrement(key, amount = 1) # :nodoc:
129
- log("decrement", key, amount)
130
- @data.decr(escape_key(key), amount)
131
- rescue Dalli::DalliError => e
132
- logger.error("DalliError: #{e.message}") if logger
133
- nil
134
- end
135
-
136
- def delete_matched(matcher, options = nil) # :nodoc:
137
- # don't do any local caching at present, just pass
138
- # through and let the error happen
139
- super
140
- raise "Not supported by Memcache"
141
- end
142
-
143
- # Clear the entire cache on all memcached servers. This method should
144
- # be used with care when using a shared cache.
145
- def clear
146
- @data.flush_all
147
- end
148
-
149
- # Get the statistics from the memcached servers.
150
- def stats
151
- @data.stats
152
- end
153
-
154
- private
155
-
156
- # Exists in 2.3.8 but not in 2.3.2 so roll our own version
157
- def expires_in(options)
158
- expires_in = (options && options[:expires_in]) || @expires_in
159
-
160
- raise ":expires_in must be a number" if expires_in && !expires_in.is_a?(Numeric)
161
-
162
- expires_in || 0
163
- end
164
-
165
- def escape_key(key)
166
- prefix = @namespace.is_a?(Proc) ? @namespace.call : @namespace
167
- key = "#{prefix}:#{key}" if prefix
168
- key
169
- end
170
- end
171
- end
172
- end