dalli 0.10.0 → 0.10.1
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/History.md +7 -0
- data/README.md +9 -1
- data/lib/action_controller/session/dalli_store.rb +5 -0
- data/lib/dalli.rb +6 -0
- data/lib/dalli/client.rb +4 -2
- data/lib/dalli/server.rb +17 -17
- data/lib/dalli/version.rb +1 -1
- data/test/test_encoding.rb +34 -0
- metadata +5 -3
data/History.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
Dalli Changelog
|
2
2
|
=====================
|
3
3
|
|
4
|
+
0.10.1
|
5
|
+
======
|
6
|
+
|
7
|
+
- Prefer server config from environment, fixes Heroku session store issues (thanks JoshMcKin)
|
8
|
+
- Better handling of non-ASCII values (size -> bytesize)
|
9
|
+
- Assert that keys are ASCII only
|
10
|
+
|
4
11
|
0.10.0
|
5
12
|
======
|
6
13
|
|
data/README.md
CHANGED
@@ -59,7 +59,7 @@ In `config/environments/production.rb`:
|
|
59
59
|
A more comprehensive example (note that we are setting a reasonable default for maximum cache entry lifetime (one day), enabling compression for large values, and namespacing all entries for this rails app. Remove the namespace if you have multiple apps which share cached values):
|
60
60
|
|
61
61
|
config.cache_store = :dalli_store, 'cache-1.example.com', 'cache-2.example.com',
|
62
|
-
:namespace => NAME_OF_RAILS_APP, :expires_in => 1.day, :compress => true, :compress_threshold => 64
|
62
|
+
{ :namespace => NAME_OF_RAILS_APP, :expires_in => 1.day, :compress => true, :compress_threshold => 64*1024 }
|
63
63
|
|
64
64
|
To use Dalli for Rails session storage, in `config/initializers/session_store.rb`:
|
65
65
|
|
@@ -83,6 +83,14 @@ In `config/environments/production.rb`:
|
|
83
83
|
In `config/initializers/session_store.rb`:
|
84
84
|
|
85
85
|
# Session cache
|
86
|
+
ActionController::Base.session = {
|
87
|
+
:namespace => 'sessions',
|
88
|
+
:expire_after => 20.minutes.to_i,
|
89
|
+
:memcache_server => ['server-1:11211', 'server-2:11211'],
|
90
|
+
:key => ...,
|
91
|
+
:secret => ...
|
92
|
+
}
|
93
|
+
|
86
94
|
require 'action_controller/session/dalli_store'
|
87
95
|
ActionController::Base.session_store = :dalli_store
|
88
96
|
|
@@ -17,6 +17,8 @@ begin
|
|
17
17
|
:memcache_server => 'localhost:11211'
|
18
18
|
}.merge(@default_options)
|
19
19
|
|
20
|
+
Rails.logger.debug("Using Dalli #{Dalli::VERSION} for session store at #{@default_options[:memcache_server].inspect}")
|
21
|
+
|
20
22
|
@pool = Dalli::Client.new(@default_options[:memcache_server], @default_options)
|
21
23
|
super
|
22
24
|
end
|
@@ -27,6 +29,7 @@ begin
|
|
27
29
|
begin
|
28
30
|
session = @pool.get(sid) || {}
|
29
31
|
rescue Dalli::DalliError
|
32
|
+
Rails.logger.warn("Session::DalliStore#get: #{$!.message}")
|
30
33
|
session = {}
|
31
34
|
end
|
32
35
|
[sid, session]
|
@@ -38,6 +41,7 @@ begin
|
|
38
41
|
@pool.set(sid, session_data, expiry)
|
39
42
|
return true
|
40
43
|
rescue Dalli::DalliError
|
44
|
+
Rails.logger.warn("Session::DalliStore#set: #{$!.message}")
|
41
45
|
return false
|
42
46
|
end
|
43
47
|
|
@@ -46,6 +50,7 @@ begin
|
|
46
50
|
@pool.delete(sid)
|
47
51
|
end
|
48
52
|
rescue Dalli::DalliError
|
53
|
+
Rails.logger.warn("Session::DalliStore#destroy: #{$!.message}")
|
49
54
|
false
|
50
55
|
end
|
51
56
|
|
data/lib/dalli.rb
CHANGED
data/lib/dalli/client.rb
CHANGED
@@ -16,7 +16,7 @@ module Dalli
|
|
16
16
|
# :threadsafe - ensure that only one thread is actively using a socket at a time. Default: true.
|
17
17
|
#
|
18
18
|
def initialize(servers=nil, options={})
|
19
|
-
@servers =
|
19
|
+
@servers = env_servers || servers || 'localhost:11211'
|
20
20
|
@options = options
|
21
21
|
end
|
22
22
|
|
@@ -185,7 +185,9 @@ module Dalli
|
|
185
185
|
end
|
186
186
|
|
187
187
|
def validate_key(key)
|
188
|
-
raise ArgumentError, "illegal character in key #{key
|
188
|
+
raise ArgumentError, "illegal character in key #{key}" if key.respond_to?(:ascii_only?) && !key.ascii_only?
|
189
|
+
raise ArgumentError, "illegal character in key #{key}" if key =~ /\s/
|
190
|
+
raise ArgumentError, "illegal character in key #{key}" if key =~ /[\x00-\x20\x80-\xFF]/
|
189
191
|
raise ArgumentError, "key cannot be blank" if key.nil? || key.strip.size == 0
|
190
192
|
raise ArgumentError, "key too long #{key.inspect}" if key.length > 250
|
191
193
|
@options[:namespace] ? "#{@options[:namespace]}:#{key}" : key
|
data/lib/dalli/server.rb
CHANGED
@@ -99,20 +99,20 @@ module Dalli
|
|
99
99
|
ONE_MB = 1024 * 1024
|
100
100
|
|
101
101
|
def get(key)
|
102
|
-
req = [REQUEST, OPCODES[:get], key.
|
102
|
+
req = [REQUEST, OPCODES[:get], key.bytesize, 0, 0, 0, key.bytesize, 0, 0, key].pack(FORMAT[:get])
|
103
103
|
write(req)
|
104
104
|
generic_response
|
105
105
|
end
|
106
106
|
|
107
107
|
def getkq(key)
|
108
|
-
req = [REQUEST, OPCODES[:getkq], key.
|
108
|
+
req = [REQUEST, OPCODES[:getkq], key.bytesize, 0, 0, 0, key.bytesize, 0, 0, key].pack(FORMAT[:getkq])
|
109
109
|
write(req)
|
110
110
|
end
|
111
111
|
|
112
112
|
def set(key, value, ttl)
|
113
|
-
raise Dalli::DalliError, "Value too large, memcached can only store 1MB of data per key" if value.
|
113
|
+
raise Dalli::DalliError, "Value too large, memcached can only store 1MB of data per key" if value.bytesize > ONE_MB
|
114
114
|
|
115
|
-
req = [REQUEST, OPCODES[multi? ? :setq : :set], key.
|
115
|
+
req = [REQUEST, OPCODES[multi? ? :setq : :set], key.bytesize, 8, 0, 0, value.bytesize + key.bytesize + 8, 0, 0, 0, ttl, key, value].pack(FORMAT[:set])
|
116
116
|
write(req)
|
117
117
|
generic_response unless multi?
|
118
118
|
end
|
@@ -124,21 +124,21 @@ module Dalli
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def add(key, value, ttl, cas)
|
127
|
-
raise Dalli::DalliError, "Value too large, memcached can only store 1MB of data per key" if value.
|
127
|
+
raise Dalli::DalliError, "Value too large, memcached can only store 1MB of data per key" if value.bytesize > ONE_MB
|
128
128
|
|
129
|
-
req = [REQUEST, OPCODES[multi? ? :addq : :add], key.
|
129
|
+
req = [REQUEST, OPCODES[multi? ? :addq : :add], key.bytesize, 8, 0, 0, value.bytesize + key.bytesize + 8, 0, cas, 0, ttl, key, value].pack(FORMAT[:add])
|
130
130
|
write(req)
|
131
131
|
generic_response unless multi?
|
132
132
|
end
|
133
133
|
|
134
134
|
def append(key, value)
|
135
|
-
req = [REQUEST, OPCODES[:append], key.
|
135
|
+
req = [REQUEST, OPCODES[:append], key.bytesize, 0, 0, 0, value.bytesize + key.bytesize, 0, 0, key, value].pack(FORMAT[:append])
|
136
136
|
write(req)
|
137
137
|
generic_response
|
138
138
|
end
|
139
139
|
|
140
140
|
def delete(key)
|
141
|
-
req = [REQUEST, OPCODES[multi? ? :deleteq : :delete], key.
|
141
|
+
req = [REQUEST, OPCODES[multi? ? :deleteq : :delete], key.bytesize, 0, 0, 0, key.bytesize, 0, 0, key].pack(FORMAT[:delete])
|
142
142
|
write(req)
|
143
143
|
generic_response unless multi?
|
144
144
|
end
|
@@ -148,7 +148,7 @@ module Dalli
|
|
148
148
|
default ||= 0
|
149
149
|
(h, l) = split(count)
|
150
150
|
(dh, dl) = split(default)
|
151
|
-
req = [REQUEST, OPCODES[:decr], key.
|
151
|
+
req = [REQUEST, OPCODES[:decr], key.bytesize, 20, 0, 0, key.bytesize + 20, 0, 0, h, l, dh, dl, expiry, key].pack(FORMAT[:decr])
|
152
152
|
write(req)
|
153
153
|
body = generic_response
|
154
154
|
body ? longlong(*body.unpack('NN')) : body
|
@@ -159,7 +159,7 @@ module Dalli
|
|
159
159
|
default ||= 0
|
160
160
|
(h, l) = split(count)
|
161
161
|
(dh, dl) = split(default)
|
162
|
-
req = [REQUEST, OPCODES[:incr], key.
|
162
|
+
req = [REQUEST, OPCODES[:incr], key.bytesize, 20, 0, 0, key.bytesize + 20, 0, 0, h, l, dh, dl, expiry, key].pack(FORMAT[:incr])
|
163
163
|
write(req)
|
164
164
|
body = generic_response
|
165
165
|
body ? longlong(*body.unpack('NN')) : body
|
@@ -174,25 +174,25 @@ module Dalli
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def prepend(key, value)
|
177
|
-
req = [REQUEST, OPCODES[:prepend], key.
|
177
|
+
req = [REQUEST, OPCODES[:prepend], key.bytesize, 0, 0, 0, value.bytesize + key.bytesize, 0, 0, key, value].pack(FORMAT[:prepend])
|
178
178
|
write(req)
|
179
179
|
generic_response
|
180
180
|
end
|
181
181
|
|
182
182
|
def replace(key, value, ttl)
|
183
|
-
req = [REQUEST, OPCODES[multi? ? :replaceq : :replace], key.
|
183
|
+
req = [REQUEST, OPCODES[multi? ? :replaceq : :replace], key.bytesize, 8, 0, 0, value.bytesize + key.bytesize + 8, 0, 0, 0, ttl, key, value].pack(FORMAT[:replace])
|
184
184
|
write(req)
|
185
185
|
generic_response unless multi?
|
186
186
|
end
|
187
187
|
|
188
188
|
def stats(info='')
|
189
|
-
req = [REQUEST, OPCODES[:stat], info.
|
189
|
+
req = [REQUEST, OPCODES[:stat], info.bytesize, 0, 0, 0, info.bytesize, 0, 0, info].pack(FORMAT[:stat])
|
190
190
|
write(req)
|
191
191
|
keyvalue_response
|
192
192
|
end
|
193
193
|
|
194
194
|
def cas(key)
|
195
|
-
req = [REQUEST, OPCODES[:get], key.
|
195
|
+
req = [REQUEST, OPCODES[:get], key.bytesize, 0, 0, 0, key.bytesize, 0, 0, key].pack(FORMAT[:get])
|
196
196
|
write(req)
|
197
197
|
cas_response
|
198
198
|
end
|
@@ -314,8 +314,8 @@ module Dalli
|
|
314
314
|
value = ''
|
315
315
|
begin
|
316
316
|
loop do
|
317
|
-
value << socket.sysread(count - value.
|
318
|
-
break if value.
|
317
|
+
value << socket.sysread(count - value.bytesize)
|
318
|
+
break if value.bytesize == count
|
319
319
|
end
|
320
320
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
321
321
|
if IO.select([socket], nil, nil, TIMEOUT)
|
@@ -449,7 +449,7 @@ module Dalli
|
|
449
449
|
msg = sasl.start[1]
|
450
450
|
mechanism = sasl.name
|
451
451
|
#p [mechanism, msg]
|
452
|
-
req = [REQUEST, OPCODES[:auth_request], mechanism.
|
452
|
+
req = [REQUEST, OPCODES[:auth_request], mechanism.bytesize, 0, 0, 0, mechanism.bytesize + msg.bytesize, 0, 0, mechanism, msg].pack(FORMAT[:auth_request])
|
453
453
|
socket.write(req)
|
454
454
|
|
455
455
|
header = read(24, socket)
|
data/lib/dalli/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'helper'
|
3
|
+
require 'memcached_mock'
|
4
|
+
|
5
|
+
class TestEncoding < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context 'using a live server' do
|
8
|
+
should 'support i18n content' do
|
9
|
+
memcached do |dc|
|
10
|
+
key = 'foo'
|
11
|
+
bad_key = utf8 = 'ƒ©åÍÎ'
|
12
|
+
|
13
|
+
assert dc.set(key, utf8)
|
14
|
+
assert_equal utf8, dc.get(key)
|
15
|
+
|
16
|
+
# keys must be ASCII
|
17
|
+
assert_raise ArgumentError, /illegal character/ do
|
18
|
+
dc.set(bad_key, utf8)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'support content expiry' do
|
24
|
+
memcached do |dc|
|
25
|
+
key = 'foo'
|
26
|
+
assert dc.set(key, 'bar', 1)
|
27
|
+
assert_equal 'bar', dc.get(key)
|
28
|
+
sleep 1.1
|
29
|
+
assert_equal nil, dc.get(key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 10
|
8
|
-
-
|
9
|
-
version: 0.10.
|
8
|
+
- 1
|
9
|
+
version: 0.10.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mike Perham
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-22 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- test/memcached_mock.rb
|
111
111
|
- test/test_active_support.rb
|
112
112
|
- test/test_dalli.rb
|
113
|
+
- test/test_encoding.rb
|
113
114
|
- test/test_network.rb
|
114
115
|
- test/test_session_store.rb
|
115
116
|
has_rdoc: true
|
@@ -151,5 +152,6 @@ test_files:
|
|
151
152
|
- test/memcached_mock.rb
|
152
153
|
- test/test_active_support.rb
|
153
154
|
- test/test_dalli.rb
|
155
|
+
- test/test_encoding.rb
|
154
156
|
- test/test_network.rb
|
155
157
|
- test/test_session_store.rb
|