memcached_store 0.11.3 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_support/cache/memcached_store.rb +45 -5
- data/lib/memcached_store/version.rb +1 -1
- data/memcached_store.gemspec +2 -2
- data/test/test_memcached_store.rb +67 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 171a18683c77797d79f6c336d29904a50120607b
|
4
|
+
data.tar.gz: 3b2dc285bb4064f3b73dd620174934527a03cf5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52711d0a3a25db301f523fb90b097392d653965876d93d24e80cedc542526b345f825a1e61a32d116a94a963024aebdf36264a076712f64841977836138cc467
|
7
|
+
data.tar.gz: d6dbb652bc7fc0b58ee187ca023e512723daa77095aa8333f78af6dc14345d8f120250d0fd88801763555cb2582aa05429f08bb7b1b4ac886dee04d0f2d5d013
|
@@ -64,6 +64,41 @@ module ActiveSupport
|
|
64
64
|
{}
|
65
65
|
end
|
66
66
|
|
67
|
+
def cas(name, options = nil)
|
68
|
+
options = merged_options(options)
|
69
|
+
options.merge!(:raw => true)
|
70
|
+
key = namespaced_key(name, options)
|
71
|
+
|
72
|
+
@data.cas(key, expiration(options), true) do |raw_value|
|
73
|
+
entry = deserialize_entry(raw_value)
|
74
|
+
value = yield entry.value
|
75
|
+
serialize_entry(Entry.new(value, options), options)
|
76
|
+
end
|
77
|
+
rescue *NONFATAL_EXCEPTIONS => e
|
78
|
+
@data.log_exception(e)
|
79
|
+
false
|
80
|
+
end
|
81
|
+
|
82
|
+
def cas_multi(*names)
|
83
|
+
options = names.extract_options!
|
84
|
+
options = merged_options(options)
|
85
|
+
options.merge!(:raw => true)
|
86
|
+
keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
|
87
|
+
|
88
|
+
@data.cas(keys_to_names.keys, expiration(options), true) do |raw_values|
|
89
|
+
values = {}
|
90
|
+
raw_values.each do |key, raw_value|
|
91
|
+
entry = deserialize_entry(raw_value)
|
92
|
+
values[keys_to_names[key]] = entry.value unless entry.expired?
|
93
|
+
end
|
94
|
+
values = yield values
|
95
|
+
Hash[values.map{|name, value| [escape_key(namespaced_key(name, options)), serialize_entry(Entry.new(value, options), options)]}]
|
96
|
+
end
|
97
|
+
rescue *NONFATAL_EXCEPTIONS => e
|
98
|
+
@data.log_exception(e)
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
67
102
|
def increment(name, amount = 1, options = nil) # :nodoc:
|
68
103
|
options = merged_options(options)
|
69
104
|
instrument(:increment, name, :amount => amount) do
|
@@ -106,11 +141,7 @@ module ActiveSupport
|
|
106
141
|
|
107
142
|
def write_entry(key, entry, options) # :nodoc:
|
108
143
|
method = options && options[:unless_exist] ? :add : :set
|
109
|
-
expires_in = options
|
110
|
-
if expires_in > 0 && !options[:raw]
|
111
|
-
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
112
|
-
expires_in += 5.minutes
|
113
|
-
end
|
144
|
+
expires_in = expiration(options)
|
114
145
|
value = serialize_entry(entry, options)
|
115
146
|
@data.send(method, escape_key(key), value, expires_in, options[:raw])
|
116
147
|
rescue *NONFATAL_EXCEPTIONS => e
|
@@ -150,6 +181,15 @@ module ActiveSupport
|
|
150
181
|
entry
|
151
182
|
end
|
152
183
|
|
184
|
+
def expiration(options)
|
185
|
+
expires_in = options[:expires_in].to_i
|
186
|
+
if expires_in > 0 && !options[:raw]
|
187
|
+
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
188
|
+
expires_in += 5.minutes
|
189
|
+
end
|
190
|
+
expires_in
|
191
|
+
end
|
192
|
+
|
153
193
|
end
|
154
194
|
end
|
155
195
|
end
|
data/memcached_store.gemspec
CHANGED
@@ -4,8 +4,8 @@ $:.unshift lib unless $:.include?(lib)
|
|
4
4
|
require "memcached_store/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
|
-
gem.authors = ["Camilo Lopez", "Tom Burns", "Arthur Neves"]
|
8
|
-
gem.email = ["camilo@camilolopez.com", "tom.burns@shopify.com", "arthurnn@gmail.com"]
|
7
|
+
gem.authors = ["Camilo Lopez", "Tom Burns", "Arthur Neves", "Francis Bogsanyi"]
|
8
|
+
gem.email = ["camilo@camilolopez.com", "tom.burns@shopify.com", "arthurnn@gmail.com", "francis.bogsanyi@shopify.com"]
|
9
9
|
gem.summary = gem.description = %q{Plugin-able Memcached adapters to add features (compression, safety)}
|
10
10
|
gem.homepage = "https://github.com/Shopify/memcached_store/"
|
11
11
|
|
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestMemcachedStore < ActiveSupport::TestCase
|
4
4
|
setup do
|
5
|
-
@cache = ActiveSupport::Cache.lookup_store(:memcached_store, expires_in: 60)
|
5
|
+
@cache = ActiveSupport::Cache.lookup_store(:memcached_store, expires_in: 60, support_cas: true)
|
6
6
|
@cache.clear
|
7
7
|
end
|
8
8
|
|
@@ -51,6 +51,72 @@ class TestMemcachedStore < ActiveSupport::TestCase
|
|
51
51
|
assert_nil @cache.fetch('foo') { 'baz' }
|
52
52
|
end
|
53
53
|
|
54
|
+
def test_cas
|
55
|
+
@cache.write('foo', nil)
|
56
|
+
assert @cache.cas('foo') {|value| assert_nil value; 'bar' }
|
57
|
+
assert_equal 'bar', @cache.read('foo')
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_cas_with_cache_miss
|
61
|
+
refute @cache.cas('not_exist') {|value| flunk }
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_cas_with_conflict
|
65
|
+
@cache.write('foo', 'bar')
|
66
|
+
refute @cache.cas('foo') {|value|
|
67
|
+
@cache.write('foo', 'baz')
|
68
|
+
'biz'
|
69
|
+
}
|
70
|
+
assert_equal 'baz', @cache.read('foo')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_cas_multi_with_empty_set
|
74
|
+
refute @cache.cas_multi() {|hash| flunk }
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_cas_multi
|
78
|
+
@cache.write('foo', 'bar')
|
79
|
+
@cache.write('fud', 'biz')
|
80
|
+
assert @cache.cas_multi('foo', 'fud') {|hash| assert_equal({"foo" => "bar", "fud" => "biz"}, hash); {"foo" => "baz", "fud" => "buz"} }
|
81
|
+
assert_equal({"foo" => "baz", "fud" => "buz"}, @cache.read_multi('foo', 'fud'))
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_cas_multi_with_altered_key
|
85
|
+
@cache.write('foo', 'baz')
|
86
|
+
assert @cache.cas_multi('foo') {|hash| {'fu' => 'baz'}}
|
87
|
+
assert_nil @cache.read('fu')
|
88
|
+
assert_equal 'baz', @cache.read('foo')
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_cas_multi_with_cache_miss
|
92
|
+
assert @cache.cas_multi('not_exist') {|hash| assert hash.empty?; {} }
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_cas_multi_with_partial_miss
|
96
|
+
@cache.write('foo', 'baz')
|
97
|
+
assert @cache.cas_multi('foo', 'bar') {|hash| assert_equal({"foo" => "baz"}, hash); {} }
|
98
|
+
assert_equal 'baz', @cache.read('foo')
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_cas_multi_with_partial_update
|
102
|
+
@cache.write('foo', 'bar')
|
103
|
+
@cache.write('fud', 'biz')
|
104
|
+
assert @cache.cas_multi('foo', 'fud') {|hash| assert_equal({"foo" => "bar", "fud" => "biz"}, hash); {"foo" => "baz"} }
|
105
|
+
assert_equal({"foo" => "baz", "fud" => "biz"}, @cache.read_multi('foo', 'fud'))
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_cas_multi_with_partial_conflict
|
109
|
+
@cache.write('foo', 'bar')
|
110
|
+
@cache.write('fud', 'biz')
|
111
|
+
result = @cache.cas_multi('foo', 'fud') do |hash|
|
112
|
+
assert_equal({"foo" => "bar", "fud" => "biz"}, hash)
|
113
|
+
@cache.write('foo', 'bad')
|
114
|
+
{"foo" => "baz", "fud" => "buz"}
|
115
|
+
end
|
116
|
+
assert result
|
117
|
+
assert_equal({"foo" => "bad", "fud" => "buz"}, @cache.read_multi('foo', 'fud'))
|
118
|
+
end
|
119
|
+
|
54
120
|
def test_should_read_and_write_hash
|
55
121
|
assert @cache.write('foo', {:a => "b"})
|
56
122
|
assert_equal({:a => "b"}, @cache.read('foo'))
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memcached_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
8
8
|
- Tom Burns
|
9
9
|
- Arthur Neves
|
10
|
+
- Francis Bogsanyi
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2014-05-
|
14
|
+
date: 2014-05-09 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: activesupport
|
@@ -115,6 +116,7 @@ email:
|
|
115
116
|
- camilo@camilolopez.com
|
116
117
|
- tom.burns@shopify.com
|
117
118
|
- arthurnn@gmail.com
|
119
|
+
- francis.bogsanyi@shopify.com
|
118
120
|
executables: []
|
119
121
|
extensions: []
|
120
122
|
extra_rdoc_files: []
|