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 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.kilobytes
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
@@ -4,6 +4,12 @@ require 'dalli/server'
4
4
  require 'dalli/version'
5
5
  require 'dalli/options'
6
6
 
7
+ unless String.respond_to?(:bytesize)
8
+ class String
9
+ alias_method :bytesize, :size
10
+ end
11
+ end
12
+
7
13
  module Dalli
8
14
  # generic error
9
15
  class DalliError < RuntimeError; end
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 = servers || env_servers || 'localhost:11211'
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.inspect}" if key =~ /\s/
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.size, 0, 0, 0, key.size, 0, 0, key].pack(FORMAT[:get])
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.size, 0, 0, 0, key.size, 0, 0, key].pack(FORMAT[:getkq])
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.size > ONE_MB
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.size, 8, 0, 0, value.size + key.size + 8, 0, 0, 0, ttl, key, value].pack(FORMAT[:set])
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.size > ONE_MB
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.size, 8, 0, 0, value.size + key.size + 8, 0, cas, 0, ttl, key, value].pack(FORMAT[:add])
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.size, 0, 0, 0, value.size + key.size, 0, 0, key, value].pack(FORMAT[:append])
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.size, 0, 0, 0, key.size, 0, 0, key].pack(FORMAT[:delete])
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.size, 20, 0, 0, key.size + 20, 0, 0, h, l, dh, dl, expiry, key].pack(FORMAT[:decr])
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.size, 20, 0, 0, key.size + 20, 0, 0, h, l, dh, dl, expiry, key].pack(FORMAT[:incr])
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.size, 0, 0, 0, value.size + key.size, 0, 0, key, value].pack(FORMAT[:prepend])
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.size, 8, 0, 0, value.size + key.size + 8, 0, 0, 0, ttl, key, value].pack(FORMAT[:replace])
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.size, 0, 0, 0, info.size, 0, 0, info].pack(FORMAT[:stat])
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.size, 0, 0, 0, key.size, 0, 0, key].pack(FORMAT[:get])
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.size)
318
- break if value.size == count
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.size, 0, 0, 0, mechanism.size + msg.size, 0, 0, mechanism, msg].pack(FORMAT[:auth_request])
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
@@ -1,3 +1,3 @@
1
1
  module Dalli
2
- VERSION = '0.10.0'
2
+ VERSION = '0.10.1'
3
3
  end
@@ -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
- - 0
9
- version: 0.10.0
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-16 00:00:00 -07:00
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