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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0004cd75061b888d9a2f577b814ebbebb6641e0c
4
- data.tar.gz: 1094e612fcbbacea703db393fb4aa1d5188675a8
3
+ metadata.gz: 171a18683c77797d79f6c336d29904a50120607b
4
+ data.tar.gz: 3b2dc285bb4064f3b73dd620174934527a03cf5a
5
5
  SHA512:
6
- metadata.gz: e9fa84e1fb05038ae55dcb562c65c191f69aa716e9272cf4533414f116865254a7f3f7dd2b781bc68230b6755e6f00d51c6e617c722887728a60c28d24a0f098
7
- data.tar.gz: f60ddc1f132a2956d3810b3295c4ed8c07bc8a21b7393e10c59cd0a253d26210d69f3af824d0428047d756910b7d797a1a9984f1b6a515e2b5cb256b49ea14be
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[:expires_in].to_i
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
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module MemcachedStore
3
- VERSION = "0.11.3"
3
+ VERSION = "0.12.0"
4
4
  end
@@ -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.11.3
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-08 00:00:00.000000000 Z
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: []