dalli 2.0.1 → 3.2.8
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 +7 -0
- data/CHANGELOG.md +671 -0
- data/Gemfile +15 -3
- data/LICENSE +1 -1
- data/README.md +33 -148
- data/lib/dalli/cas/client.rb +3 -0
- data/lib/dalli/client.rb +293 -131
- data/lib/dalli/compressor.rb +40 -0
- data/lib/dalli/key_manager.rb +121 -0
- data/lib/dalli/options.rb +22 -4
- data/lib/dalli/pid_cache.rb +40 -0
- data/lib/dalli/pipelined_getter.rb +177 -0
- data/lib/dalli/protocol/base.rb +250 -0
- data/lib/dalli/protocol/binary/request_formatter.rb +117 -0
- data/lib/dalli/protocol/binary/response_header.rb +36 -0
- data/lib/dalli/protocol/binary/response_processor.rb +239 -0
- data/lib/dalli/protocol/binary/sasl_authentication.rb +60 -0
- data/lib/dalli/protocol/binary.rb +173 -0
- data/lib/dalli/protocol/connection_manager.rb +255 -0
- data/lib/dalli/protocol/meta/key_regularizer.rb +31 -0
- data/lib/dalli/protocol/meta/request_formatter.rb +121 -0
- data/lib/dalli/protocol/meta/response_processor.rb +211 -0
- data/lib/dalli/protocol/meta.rb +178 -0
- data/lib/dalli/protocol/response_buffer.rb +54 -0
- data/lib/dalli/protocol/server_config_parser.rb +86 -0
- data/lib/dalli/protocol/ttl_sanitizer.rb +45 -0
- data/lib/dalli/protocol/value_compressor.rb +85 -0
- data/lib/dalli/protocol/value_marshaller.rb +59 -0
- data/lib/dalli/protocol/value_serializer.rb +91 -0
- data/lib/dalli/protocol.rb +19 -0
- data/lib/dalli/ring.rb +98 -50
- data/lib/dalli/server.rb +4 -524
- data/lib/dalli/servers_arg_normalizer.rb +54 -0
- data/lib/dalli/socket.rb +154 -53
- data/lib/dalli/version.rb +5 -1
- data/lib/dalli.rb +49 -13
- data/lib/rack/session/dalli.rb +169 -26
- metadata +53 -88
- data/History.md +0 -262
- data/Performance.md +0 -42
- data/Rakefile +0 -39
- data/dalli.gemspec +0 -28
- data/lib/action_dispatch/middleware/session/dalli_store.rb +0 -76
- data/lib/active_support/cache/dalli_store.rb +0 -203
- data/test/abstract_unit.rb +0 -281
- data/test/benchmark_test.rb +0 -187
- data/test/helper.rb +0 -41
- data/test/memcached_mock.rb +0 -113
- data/test/test_active_support.rb +0 -163
- data/test/test_dalli.rb +0 -461
- data/test/test_encoding.rb +0 -43
- data/test/test_failover.rb +0 -107
- data/test/test_network.rb +0 -54
- data/test/test_ring.rb +0 -85
- data/test/test_sasl.rb +0 -83
- data/test/test_session_store.rb +0 -224
data/test/test_ring.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe 'Ring' do
|
4
|
-
|
5
|
-
context 'a ring of servers' do
|
6
|
-
|
7
|
-
should "have the continuum sorted by value" do
|
8
|
-
servers = [stub(:hostname => "localhost", :port => "11211", :weight => 1),
|
9
|
-
stub(:hostname => "localhost", :port => "9500", :weight => 1)]
|
10
|
-
ring = Dalli::Ring.new(servers, {})
|
11
|
-
previous_value = 0
|
12
|
-
ring.continuum.each do |entry|
|
13
|
-
assert entry.value > previous_value
|
14
|
-
previous_value = entry.value
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
should 'raise when no servers are available/defined' do
|
19
|
-
ring = Dalli::Ring.new([], {})
|
20
|
-
assert_raises Dalli::RingError, :message => "No server available" do
|
21
|
-
ring.server_for_key('test')
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'containing only a single server' do
|
26
|
-
should "raise correctly when it's not alive" do
|
27
|
-
servers = [
|
28
|
-
Dalli::Server.new("localhost:12345"),
|
29
|
-
]
|
30
|
-
ring = Dalli::Ring.new(servers, {})
|
31
|
-
assert_raises Dalli::RingError, :message => "No server available" do
|
32
|
-
ring.server_for_key('test')
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
should "return the server when it's alive" do
|
37
|
-
servers = [
|
38
|
-
Dalli::Server.new("localhost:19191"),
|
39
|
-
]
|
40
|
-
ring = Dalli::Ring.new(servers, {})
|
41
|
-
memcached(19191) do |mc|
|
42
|
-
ring = mc.send(:ring)
|
43
|
-
assert_equal ring.servers.first.port, ring.server_for_key('test').port
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'containing multiple servers' do
|
49
|
-
should "raise correctly when no server is alive" do
|
50
|
-
servers = [
|
51
|
-
Dalli::Server.new("localhost:12345"),
|
52
|
-
Dalli::Server.new("localhost:12346"),
|
53
|
-
]
|
54
|
-
ring = Dalli::Ring.new(servers, {})
|
55
|
-
assert_raises Dalli::RingError, :message => "No server available" do
|
56
|
-
ring.server_for_key('test')
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
should "return an alive server when at least one is alive" do
|
61
|
-
servers = [
|
62
|
-
Dalli::Server.new("localhost:12346"),
|
63
|
-
Dalli::Server.new("localhost:19191"),
|
64
|
-
]
|
65
|
-
ring = Dalli::Ring.new(servers, {})
|
66
|
-
memcached(19191) do |mc|
|
67
|
-
ring = mc.send(:ring)
|
68
|
-
assert_equal ring.servers.first.port, ring.server_for_key('test').port
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
should 'detect when a dead server is up again' do
|
74
|
-
memcached(19997) do
|
75
|
-
down_retry_delay = 0.5
|
76
|
-
dc = Dalli::Client.new(['localhost:19997', 'localhost:19998'], :down_retry_delay => down_retry_delay)
|
77
|
-
assert_equal 1, dc.stats.values.compact.count
|
78
|
-
|
79
|
-
memcached(19998) do
|
80
|
-
assert_equal 2, dc.stats.values.compact.count
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
data/test/test_sasl.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe 'Sasl' do
|
4
|
-
|
5
|
-
context 'a server requiring authentication' do
|
6
|
-
|
7
|
-
context 'without authentication credentials' do
|
8
|
-
before do
|
9
|
-
ENV['MEMCACHE_USERNAME'] = 'foo'
|
10
|
-
ENV['MEMCACHE_PASSWORD'] = 'wrongpwd'
|
11
|
-
end
|
12
|
-
|
13
|
-
after do
|
14
|
-
ENV['MEMCACHE_USERNAME'] = nil
|
15
|
-
ENV['MEMCACHE_PASSWORD'] = nil
|
16
|
-
end
|
17
|
-
|
18
|
-
should 'provide one test that passes' do
|
19
|
-
assert true
|
20
|
-
end
|
21
|
-
|
22
|
-
should_eventually 'gracefully handle authentication failures' do
|
23
|
-
memcached(19124, '-S') do |dc|
|
24
|
-
assert_raise Dalli::DalliError, /32/ do
|
25
|
-
dc.set('abc', 123)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
should_eventually 'fail SASL authentication with wrong options' do
|
32
|
-
memcached(19124, '-S') do |dc|
|
33
|
-
dc = Dalli::Client.new('localhost:19124', :username => 'foo', :password => 'wrongpwd')
|
34
|
-
assert_raise Dalli::DalliError, /32/ do
|
35
|
-
dc.set('abc', 123)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# OSX: Create a SASL user for the memcached application like so:
|
41
|
-
#
|
42
|
-
# saslpasswd2 -a memcached -c testuser
|
43
|
-
#
|
44
|
-
# with password 'testtest'
|
45
|
-
context 'in an authenticated environment' do
|
46
|
-
before do
|
47
|
-
ENV['MEMCACHE_USERNAME'] = 'testuser'
|
48
|
-
ENV['MEMCACHE_PASSWORD'] = 'testtest'
|
49
|
-
end
|
50
|
-
|
51
|
-
after do
|
52
|
-
ENV['MEMCACHE_USERNAME'] = nil
|
53
|
-
ENV['MEMCACHE_PASSWORD'] = nil
|
54
|
-
end
|
55
|
-
|
56
|
-
should_eventually 'pass SASL authentication' do
|
57
|
-
memcached(19124, '-S') do |dc|
|
58
|
-
# I get "Dalli::DalliError: Error authenticating: 32" in OSX
|
59
|
-
# but SASL works on Heroku servers. YMMV.
|
60
|
-
assert_equal true, dc.set('abc', 123)
|
61
|
-
assert_equal 123, dc.get('abc')
|
62
|
-
results = dc.stats
|
63
|
-
assert_equal 1, results.size
|
64
|
-
assert_equal 38, results.values.first.size
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
should_eventually 'pass SASL authentication with options' do
|
70
|
-
memcached(19124, '-S') do |dc|
|
71
|
-
dc = Dalli::Client.new('localhost:19124', :username => 'testuser', :password => 'testtest')
|
72
|
-
# I get "Dalli::DalliError: Error authenticating: 32" in OSX
|
73
|
-
# but SASL works on Heroku servers. YMMV.
|
74
|
-
assert_equal true, dc.set('abc', 123)
|
75
|
-
assert_equal 123, dc.get('abc')
|
76
|
-
results = dc.stats
|
77
|
-
assert_equal 1, results.size
|
78
|
-
assert_equal 38, results.values.first.size
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
data/test/test_session_store.rb
DELETED
@@ -1,224 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'abstract_unit'
|
3
|
-
require 'action_dispatch/middleware/session/dalli_store'
|
4
|
-
|
5
|
-
class Foo
|
6
|
-
def initialize(bar='baz')
|
7
|
-
@bar = bar
|
8
|
-
end
|
9
|
-
def inspect
|
10
|
-
"#<#{self.class} bar:#{@bar.inspect}>"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class TestSessionStore < ActionController::IntegrationTest
|
15
|
-
class TestController < ActionController::Base
|
16
|
-
def no_session_access
|
17
|
-
head :ok
|
18
|
-
end
|
19
|
-
|
20
|
-
def set_session_value
|
21
|
-
session[:foo] = "bar"
|
22
|
-
head :ok
|
23
|
-
end
|
24
|
-
|
25
|
-
def set_serialized_session_value
|
26
|
-
session[:foo] = Foo.new
|
27
|
-
head :ok
|
28
|
-
end
|
29
|
-
|
30
|
-
def get_session_value
|
31
|
-
render :text => "foo: #{session[:foo].inspect}"
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_session_id
|
35
|
-
render :text => "#{request.session_options[:id]}"
|
36
|
-
end
|
37
|
-
|
38
|
-
def call_reset_session
|
39
|
-
session[:bar]
|
40
|
-
reset_session
|
41
|
-
session[:bar] = "baz"
|
42
|
-
head :ok
|
43
|
-
end
|
44
|
-
|
45
|
-
def rescue_action(e) raise end
|
46
|
-
end
|
47
|
-
|
48
|
-
begin
|
49
|
-
require 'dalli'
|
50
|
-
memcache = Dalli::Client.new('127.0.0.1:11211')
|
51
|
-
memcache.set('ping', '')
|
52
|
-
|
53
|
-
def test_setting_and_getting_session_value
|
54
|
-
with_test_route_set do
|
55
|
-
get '/set_session_value'
|
56
|
-
assert_response :success
|
57
|
-
assert cookies['_session_id']
|
58
|
-
|
59
|
-
get '/get_session_value'
|
60
|
-
assert_response :success
|
61
|
-
assert_equal 'foo: "bar"', response.body
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_getting_nil_session_value
|
66
|
-
with_test_route_set do
|
67
|
-
get '/get_session_value'
|
68
|
-
assert_response :success
|
69
|
-
assert_equal 'foo: nil', response.body
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_getting_session_value_after_session_reset
|
74
|
-
with_test_route_set do
|
75
|
-
get '/set_session_value'
|
76
|
-
assert_response :success
|
77
|
-
assert cookies['_session_id']
|
78
|
-
session_cookie = cookies.send(:hash_for)['_session_id']
|
79
|
-
|
80
|
-
get '/call_reset_session'
|
81
|
-
assert_response :success
|
82
|
-
assert_not_equal [], headers['Set-Cookie']
|
83
|
-
|
84
|
-
cookies << session_cookie # replace our new session_id with our old, pre-reset session_id
|
85
|
-
|
86
|
-
get '/get_session_value'
|
87
|
-
assert_response :success
|
88
|
-
assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from memcached"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_getting_from_nonexistent_session
|
93
|
-
with_test_route_set do
|
94
|
-
get '/get_session_value'
|
95
|
-
assert_response :success
|
96
|
-
assert_equal 'foo: nil', response.body
|
97
|
-
assert_nil cookies['_session_id'], "should only create session on write, not read"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_setting_session_value_after_session_reset
|
102
|
-
with_test_route_set do
|
103
|
-
get '/set_session_value'
|
104
|
-
assert_response :success
|
105
|
-
assert cookies['_session_id']
|
106
|
-
session_id = cookies['_session_id']
|
107
|
-
|
108
|
-
get '/call_reset_session'
|
109
|
-
assert_response :success
|
110
|
-
assert_not_equal [], headers['Set-Cookie']
|
111
|
-
|
112
|
-
get '/get_session_value'
|
113
|
-
assert_response :success
|
114
|
-
assert_equal 'foo: nil', response.body
|
115
|
-
|
116
|
-
get '/get_session_id'
|
117
|
-
assert_response :success
|
118
|
-
assert_not_equal session_id, response.body
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_getting_session_id
|
123
|
-
with_test_route_set do
|
124
|
-
get '/set_session_value'
|
125
|
-
assert_response :success
|
126
|
-
assert cookies['_session_id']
|
127
|
-
session_id = cookies['_session_id']
|
128
|
-
|
129
|
-
get '/get_session_id'
|
130
|
-
assert_response :success
|
131
|
-
assert_equal session_id, response.body, "should be able to read session id without accessing the session hash"
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def test_deserializes_unloaded_class
|
136
|
-
with_test_route_set do
|
137
|
-
with_autoload_path "session_autoload_test" do
|
138
|
-
get '/set_serialized_session_value'
|
139
|
-
assert_response :success
|
140
|
-
assert cookies['_session_id']
|
141
|
-
end
|
142
|
-
with_autoload_path "session_autoload_test" do
|
143
|
-
get '/get_session_id'
|
144
|
-
assert_response :success
|
145
|
-
end
|
146
|
-
with_autoload_path "session_autoload_test" do
|
147
|
-
get '/get_session_value'
|
148
|
-
assert_response :success
|
149
|
-
assert_equal 'foo: #<Foo bar:"baz">', response.body, "should auto-load unloaded class"
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def test_doesnt_write_session_cookie_if_session_id_is_already_exists
|
155
|
-
with_test_route_set do
|
156
|
-
get '/set_session_value'
|
157
|
-
assert_response :success
|
158
|
-
assert cookies['_session_id']
|
159
|
-
|
160
|
-
get '/get_session_value'
|
161
|
-
assert_response :success
|
162
|
-
assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_prevents_session_fixation
|
167
|
-
with_test_route_set do
|
168
|
-
get '/get_session_value'
|
169
|
-
assert_response :success
|
170
|
-
assert_equal 'foo: nil', response.body
|
171
|
-
session_id = cookies['_session_id']
|
172
|
-
|
173
|
-
reset!
|
174
|
-
|
175
|
-
get '/set_session_value', :_session_id => session_id
|
176
|
-
assert_response :success
|
177
|
-
assert_not_equal session_id, cookies['_session_id']
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def test_expire_after
|
182
|
-
with_test_route_set(:expire_after => 1) do
|
183
|
-
get '/set_session_value'
|
184
|
-
assert_match /expires/, @response.headers['Set-Cookie']
|
185
|
-
|
186
|
-
sleep(1)
|
187
|
-
|
188
|
-
get '/get_session_value'
|
189
|
-
assert_equal 'foo: nil', response.body
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def test_expires_in
|
194
|
-
with_test_route_set(:expires_in => 1) do
|
195
|
-
get '/set_session_value'
|
196
|
-
assert_no_match /expires/, @response.headers['Set-Cookie']
|
197
|
-
|
198
|
-
sleep(1)
|
199
|
-
|
200
|
-
get '/get_session_value'
|
201
|
-
assert_equal 'foo: nil', response.body
|
202
|
-
end
|
203
|
-
end
|
204
|
-
rescue LoadError, RuntimeError
|
205
|
-
$stderr.puts "Skipping SessionStore tests. Start memcached and try again: #{$!.message}"
|
206
|
-
end
|
207
|
-
|
208
|
-
private
|
209
|
-
|
210
|
-
def with_test_route_set(options = {})
|
211
|
-
options = {:key => '_session_id', :memcache_server => '127.0.0.1:11211'}.merge(options)
|
212
|
-
with_routing do |set|
|
213
|
-
set.draw do
|
214
|
-
match ':action', :to => ::TestSessionStore::TestController
|
215
|
-
end
|
216
|
-
|
217
|
-
@app = self.class.build_app(set) do |middleware|
|
218
|
-
middleware.use ActionDispatch::Session::DalliStore, options
|
219
|
-
end
|
220
|
-
|
221
|
-
yield
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|