fault_tolerant_redis-activesupport 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c294041252356e5f9da6aaae0afb056b72f9853
4
+ data.tar.gz: 5ebe62c437f156ec1e8bfa072546fca3784fda20
5
+ SHA512:
6
+ metadata.gz: 7e5d1629b9f420cedcd595c1dfaf7e17170636c678983029c839e8dd03ea8f0bf61be73d0313502f873f1e5d09c222782330be03dd96cdc848650a81b47b3153
7
+ data.tar.gz: dc0042f8adb6655ac7d2b90d293ab41589c5ab323f84ada2f07e9e0d051b5995aabf8684a3756c8c9756cda5ed6af4168a09da9788b94d386ff37211aa658ace
data/.env ADDED
@@ -0,0 +1,19 @@
1
+ local ruby_version_path='.ruby-version'
2
+ local ruby_gemset_path='.ruby-gemset'
3
+
4
+ if [[ -f $ruby_version_path ]]; then
5
+ local ruby_version=`cat $ruby_version_path`
6
+ fi
7
+
8
+ if [[ -f $ruby_gemset_path ]]; then
9
+ local ruby_gemset=`cat $ruby_gemset_path`
10
+ fi
11
+
12
+ if [ ! -z $ruby_version ]; then
13
+ if [ ! -z $ruby_gemset ]; then
14
+ echo `which rvm`
15
+ rvm use $ruby_version@$ruby_gemset
16
+ else
17
+ rvm use $ruby_version
18
+ fi
19
+ fi
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ *.gem
3
+ tmp/
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ script: 'bundle exec rake'
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - ruby-head
7
+ - rbx-19mode
8
+ - jruby-19mode
9
+ - jruby-head
10
+
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: jruby-head
14
+ - rvm: ruby-head
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+ ruby File.read(".ruby-version").strip
3
+ gemspec
4
+
5
+ if ::File.directory?(gem_path = '../redis-store')
6
+ gem 'redis-store', '~> 1.1.0', path: gem_path
7
+ end
8
+
9
+ gem 'i18n'
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 - 2011 Luca Guidi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Redis stores for ActiveSupport
2
+
3
+ __`redis-activesupport`__ provides a cache for __ActiveSupport__. See the main [redis-store readme](https://github.com/redis-store/redis-store) for general guidelines.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ # Gemfile
9
+ gem 'redis-activesupport'
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ If you are using redis-store with Rails, consider using the [redis-rails gem](https://github.com/redis-store/redis-rails) instead. For standalone usage:
15
+
16
+ ```ruby
17
+ ActiveSupport::Cache.lookup_store :redis_store # { ... optional configuration ... }
18
+ ```
19
+
20
+ ## Running tests
21
+
22
+ ```shell
23
+ gem install bundler
24
+ git clone git://github.com/redis-store/redis-activesupport.git
25
+ cd redis-activesupport
26
+ bundle install
27
+ bundle exec rake
28
+ ```
29
+
30
+ If you are on **Snow Leopard** you have to run `env ARCHFLAGS="-arch x86_64" bundle exec rake`
31
+
32
+ ## Status
33
+
34
+ [![Gem Version](https://badge.fury.io/rb/redis-activesupport.png)](http://badge.fury.io/rb/redis-activesupport) [![Build Status](https://secure.travis-ci.org/redis-store/redis-activesupport.png?branch=master)](http://travis-ci.org/jodosha/redis-activesupport?branch=master) [![Code Climate](https://codeclimate.com/github/jodosha/redis-store.png)](https://codeclimate.com/github/redis-store/redis-activesupport)
35
+
36
+ ## Copyright
37
+
38
+ 2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/setup'
2
+ require 'rake'
3
+ require 'bundler/gem_tasks'
4
+ require 'redis-store/testing/tasks'
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'redis/activesupport/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'fault_tolerant_redis-activesupport'
7
+ s.version = Redis::ActiveSupport::VERSION
8
+ s.authors = ['Luca Guidi', 'Jan Renra Gloser']
9
+ s.email = ['me@lucaguidi.com', 'jan.renra.gloser@gmail.com']
10
+ s.homepage = 'https://github.com/renra/redis-activesupport'
11
+ s.summary = %q{Fault tolerant redis store for ActiveSupport}
12
+ s.description = %q{Fault tolerant redis store for ActiveSupport}
13
+ s.license = 'MIT'
14
+
15
+ s.rubyforge_project = 'redis-activesupport'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ['lib']
21
+
22
+ s.add_runtime_dependency 'redis-store', '~> 1.1.0'
23
+ s.add_runtime_dependency 'activesupport', '~> 4'
24
+ s.add_runtime_dependency 'maybe_client', '1.1.0'
25
+
26
+ s.add_development_dependency 'rake', '~> 10'
27
+ s.add_development_dependency 'bundler', '~> 1.3'
28
+ s.add_development_dependency 'mocha', '~> 0.14.0'
29
+ s.add_development_dependency 'minitest', '~> 4.2'
30
+ s.add_development_dependency 'redis-store-testing'
31
+ end
32
+
@@ -0,0 +1,207 @@
1
+ # encoding: UTF-8
2
+ require 'redis-store'
3
+ require 'maybe_client'
4
+
5
+ module ActiveSupport
6
+ module Cache
7
+ class FaultTolerantRedisStore < Store
8
+ # Instantiate the store.
9
+ #
10
+ # Example:
11
+ # RedisStore.new
12
+ # # => host: localhost, port: 6379, db: 0
13
+ #
14
+ # RedisStore.new "example.com"
15
+ # # => host: example.com, port: 6379, db: 0
16
+ #
17
+ # RedisStore.new "example.com:23682"
18
+ # # => host: example.com, port: 23682, db: 0
19
+ #
20
+ # RedisStore.new "example.com:23682/1"
21
+ # # => host: example.com, port: 23682, db: 1
22
+ #
23
+ # RedisStore.new "example.com:23682/1/theplaylist"
24
+ # # => host: example.com, port: 23682, db: 1, namespace: theplaylist
25
+ #
26
+ # RedisStore.new "localhost:6379/0", "localhost:6380/0"
27
+ # # => instantiate a cluster
28
+ def initialize(*addresses)
29
+ @data = MaybeClient.new(client: ::Redis::Store::Factory.create(addresses))
30
+ super(addresses.extract_options!)
31
+ end
32
+
33
+ def write(name, value, options = nil)
34
+ options = merged_options(options)
35
+ instrument(:write, name, options) do |payload|
36
+ entry = options[:raw].present? ? value : Entry.new(value, options)
37
+ write_entry(namespaced_key(name, options), entry, options)
38
+ end
39
+ end
40
+
41
+ # Delete objects for matched keys.
42
+ #
43
+ # Performance note: this operation can be dangerous for large production
44
+ # databases, as it uses the Redis "KEYS" command, which is O(N) over the
45
+ # total number of keys in the database. Users of large Redis caches should
46
+ # avoid this method.
47
+ #
48
+ # Example:
49
+ # cache.del_matched "rab*"
50
+ def delete_matched(matcher, options = nil)
51
+ options = merged_options(options)
52
+ instrument(:delete_matched, matcher.inspect) do
53
+ matcher = key_matcher(matcher, options)
54
+ begin
55
+ !(keys = @data.keys(matcher)).empty? && @data.del(*keys)
56
+ rescue Errno::ECONNREFUSED => e
57
+ false
58
+ end
59
+ end
60
+ end
61
+
62
+ # Reads multiple keys from the cache using a single call to the
63
+ # servers for all keys. Options can be passed in the last argument.
64
+ #
65
+ # Example:
66
+ # cache.read_multi "rabbit", "white-rabbit"
67
+ # cache.read_multi "rabbit", "white-rabbit", :raw => true
68
+ def read_multi(*names)
69
+ values = @data.mget(*names)
70
+ values.map! { |v| v.is_a?(ActiveSupport::Cache::Entry) ? v.value : v }
71
+
72
+ # Remove the options hash before mapping keys to values
73
+ names.extract_options!
74
+
75
+ result = Hash[names.zip(values)]
76
+ result.reject!{ |k,v| v.nil? }
77
+ result
78
+ end
79
+
80
+ # Increment a key in the store.
81
+ #
82
+ # If the key doesn't exist it will be initialized on 0.
83
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
84
+ #
85
+ # Example:
86
+ # We have two objects in cache:
87
+ # counter # => 23
88
+ # rabbit # => #<Rabbit:0x5eee6c>
89
+ #
90
+ # cache.increment "counter"
91
+ # cache.read "counter", :raw => true # => "24"
92
+ #
93
+ # cache.increment "counter", 6
94
+ # cache.read "counter", :raw => true # => "30"
95
+ #
96
+ # cache.increment "a counter"
97
+ # cache.read "a counter", :raw => true # => "1"
98
+ #
99
+ # cache.increment "rabbit"
100
+ # cache.read "rabbit", :raw => true # => "1"
101
+ def increment(key, amount = 1)
102
+ instrument(:increment, key, :amount => amount) do
103
+ @data.incrby key, amount
104
+ end
105
+ end
106
+
107
+ # Decrement a key in the store
108
+ #
109
+ # If the key doesn't exist it will be initialized on 0.
110
+ # If the key exist but it isn't a Fixnum it will be initialized on 0.
111
+ #
112
+ # Example:
113
+ # We have two objects in cache:
114
+ # counter # => 23
115
+ # rabbit # => #<Rabbit:0x5eee6c>
116
+ #
117
+ # cache.decrement "counter"
118
+ # cache.read "counter", :raw => true # => "22"
119
+ #
120
+ # cache.decrement "counter", 2
121
+ # cache.read "counter", :raw => true # => "20"
122
+ #
123
+ # cache.decrement "a counter"
124
+ # cache.read "a counter", :raw => true # => "-1"
125
+ #
126
+ # cache.decrement "rabbit"
127
+ # cache.read "rabbit", :raw => true # => "-1"
128
+ def decrement(key, amount = 1)
129
+ instrument(:decrement, key, :amount => amount) do
130
+ @data.decrby key, amount
131
+ end
132
+ end
133
+
134
+ def expire(key, ttl)
135
+ @data.expire key, ttl
136
+ end
137
+
138
+ # Clear all the data from the store.
139
+ def clear
140
+ instrument(:clear, nil, nil) do
141
+ @data.flushdb
142
+ end
143
+ end
144
+
145
+ # fixed problem with invalid exists? method
146
+ # https://github.com/rails/rails/commit/cad2c8f5791d5bd4af0f240d96e00bae76eabd2f
147
+ def exist?(name, options = nil)
148
+ res = super(name, options)
149
+ res || false
150
+ end
151
+
152
+ def stats
153
+ @data.info
154
+ end
155
+
156
+ # Force client reconnection, useful Unicorn deployed apps.
157
+ def reconnect
158
+ @data.reconnect
159
+ end
160
+
161
+ protected
162
+ def write_entry(key, entry, options)
163
+ method = options && options[:unless_exist] ? :setnx : :set
164
+ @data.send method, key, entry, options
165
+ rescue Errno::ECONNREFUSED => e
166
+ false
167
+ end
168
+
169
+ def read_entry(key, options)
170
+ entry = @data.get key, options
171
+ if entry
172
+ entry.is_a?(ActiveSupport::Cache::Entry) ? entry : ActiveSupport::Cache::Entry.new(entry)
173
+ end
174
+ rescue Errno::ECONNREFUSED => e
175
+ nil
176
+ end
177
+
178
+ ##
179
+ # Implement the ActiveSupport::Cache#delete_entry
180
+ #
181
+ # It's really needed and use
182
+ #
183
+ def delete_entry(key, options)
184
+ @data.del key
185
+ rescue Errno::ECONNREFUSED => e
186
+ false
187
+ end
188
+
189
+
190
+ # Add the namespace defined in the options to a pattern designed to match keys.
191
+ #
192
+ # This implementation is __different__ than ActiveSupport:
193
+ # __it doesn't accept Regular expressions__, because the Redis matcher is designed
194
+ # only for strings with wildcards.
195
+ def key_matcher(pattern, options)
196
+ prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
197
+ if prefix
198
+ raise "Regexps aren't supported, please use string with wildcards." if pattern.is_a?(Regexp)
199
+ "#{prefix}:#{pattern}"
200
+ else
201
+ pattern
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+
@@ -0,0 +1,4 @@
1
+ require 'redis-store'
2
+ require 'active_support'
3
+ require 'redis/activesupport/version'
4
+ require 'active_support/cache/fault_tolerant_redis_store'
@@ -0,0 +1,5 @@
1
+ class Redis
2
+ module ActiveSupport
3
+ VERSION = '4.0.0'
4
+ end
5
+ end
@@ -0,0 +1,320 @@
1
+ require 'test_helper'
2
+
3
+ describe ActiveSupport::Cache::RedisStore do
4
+ def setup
5
+ @store = ActiveSupport::Cache::RedisStore.new
6
+ @dstore = ActiveSupport::Cache::RedisStore.new "redis://127.0.0.1:6380/1", "redis://127.0.0.1:6381/1"
7
+ @rabbit = OpenStruct.new :name => "bunny"
8
+ @white_rabbit = OpenStruct.new :color => "white"
9
+
10
+ with_store_management do |store|
11
+ store.write "rabbit", @rabbit
12
+ store.delete "counter"
13
+ store.delete "rub-a-dub"
14
+ end
15
+ end
16
+
17
+ it "reads the data" do
18
+ with_store_management do |store|
19
+ store.read("rabbit").must_equal(@rabbit)
20
+ end
21
+ end
22
+
23
+ it "writes the data" do
24
+ with_store_management do |store|
25
+ store.write "rabbit", @white_rabbit
26
+ store.read("rabbit").must_equal(@white_rabbit)
27
+ end
28
+ end
29
+
30
+ it "writes the data with expiration time" do
31
+ with_store_management do |store|
32
+ store.write "rabbit", @white_rabbit, :expires_in => 1.second
33
+ store.read("rabbit").must_equal(@white_rabbit)
34
+ sleep 2
35
+ store.read("rabbit").must_be_nil
36
+ end
37
+ end
38
+
39
+ it "respects expiration time in seconds" do
40
+ with_store_management do |store|
41
+ store.write "rabbit", @white_rabbit
42
+ store.read("rabbit").must_equal(@white_rabbit)
43
+ store.expire "rabbit", 1.seconds
44
+ sleep 2
45
+ store.read("rabbit").must_be_nil
46
+ end
47
+ end
48
+
49
+ it "respects expiration time in minutes" do
50
+ with_store_management do |store|
51
+ store.write "rabbit", @white_rabbit
52
+ store.read("rabbit").must_equal(@white_rabbit)
53
+ store.expire "rabbit", 1.minutes
54
+ sleep 61
55
+ store.read("rabbit").must_be_nil
56
+ end
57
+ end
58
+
59
+ it "does't write data if :unless_exist option is true" do
60
+ with_store_management do |store|
61
+ store.write "rabbit", @white_rabbit, :unless_exist => true
62
+ store.read("rabbit").must_equal(@rabbit)
63
+ end
64
+ end
65
+
66
+ if RUBY_VERSION.match /1\.9/
67
+ it "reads raw data" do
68
+ with_store_management do |store|
69
+ result = store.read("rabbit", :raw => true)
70
+ result.must_include("ActiveSupport::Cache::Entry")
71
+ result.must_include("\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF")
72
+ end
73
+ end
74
+ else
75
+ it "reads raw data" do
76
+ with_store_management do |store|
77
+ result = store.read("rabbit", :raw => true)
78
+ result.must_include("ActiveSupport::Cache::Entry")
79
+ result.must_include("\017OpenStruct{\006:\tname")
80
+ end
81
+ end
82
+ end
83
+
84
+ it "writes raw data" do
85
+ with_store_management do |store|
86
+ store.write "rabbit", @white_rabbit, :raw => true
87
+ store.read("rabbit", :raw => true).must_equal(%(#<OpenStruct color=\"white\">))
88
+ end
89
+ end
90
+
91
+ it "deletes data" do
92
+ with_store_management do |store|
93
+ store.delete "rabbit"
94
+ store.read("rabbit").must_be_nil
95
+ end
96
+ end
97
+
98
+ it "deletes matched data" do
99
+ with_store_management do |store|
100
+ store.delete_matched "rabb*"
101
+ store.read("rabbit").must_be_nil
102
+ end
103
+ end
104
+
105
+ it "verifies existence of an object in the store" do
106
+ with_store_management do |store|
107
+ store.exist?("rabbit").must_equal(true)
108
+ store.exist?("rab-a-dub").must_equal(false)
109
+ end
110
+ end
111
+
112
+ it "increments a key" do
113
+ with_store_management do |store|
114
+ 3.times { store.increment "counter" }
115
+ store.read("counter", :raw => true).to_i.must_equal(3)
116
+ end
117
+ end
118
+
119
+ it "decrements a key" do
120
+ with_store_management do |store|
121
+ 3.times { store.increment "counter" }
122
+ 2.times { store.decrement "counter" }
123
+ store.read("counter", :raw => true).to_i.must_equal(1)
124
+ end
125
+ end
126
+
127
+ it "increments a raw key" do
128
+ with_store_management do |store|
129
+ assert store.write("raw-counter", 1, :raw => true)
130
+ store.increment("raw-counter", 2)
131
+ store.read("raw-counter", :raw => true).to_i.must_equal(3)
132
+ end
133
+ end
134
+
135
+ it "decrements a raw key" do
136
+ with_store_management do |store|
137
+ assert store.write("raw-counter", 3, :raw => true)
138
+ store.decrement("raw-counter", 2)
139
+ store.read("raw-counter", :raw => true).to_i.must_equal(1)
140
+ end
141
+ end
142
+
143
+ it "increments a key by given value" do
144
+ with_store_management do |store|
145
+ store.increment "counter", 3
146
+ store.read("counter", :raw => true).to_i.must_equal(3)
147
+ end
148
+ end
149
+
150
+ it "decrements a key by given value" do
151
+ with_store_management do |store|
152
+ 3.times { store.increment "counter" }
153
+ store.decrement "counter", 2
154
+ store.read("counter", :raw => true).to_i.must_equal(1)
155
+ end
156
+ end
157
+
158
+ it "clears the store" do
159
+ with_store_management do |store|
160
+ store.clear
161
+ store.instance_variable_get(:@data).keys("*").flatten.must_be_empty
162
+ end
163
+ end
164
+
165
+ it "provides store stats" do
166
+ with_store_management do |store|
167
+ store.stats.wont_be_empty
168
+ end
169
+ end
170
+
171
+ it "fetches data" do
172
+ with_store_management do |store|
173
+ store.fetch("rabbit").must_equal(@rabbit)
174
+ store.fetch("rub-a-dub").must_be_nil
175
+ store.fetch("rub-a-dub") { "Flora de Cana" }
176
+ store.fetch("rub-a-dub").must_equal("Flora de Cana")
177
+ store.fetch("rabbit", :force => true) # force cache miss
178
+ store.fetch("rabbit", :force => true, :expires_in => 1.second) { @white_rabbit }
179
+ # store.fetch("rabbit").must_equal(@white_rabbit)
180
+ sleep 2
181
+ store.fetch("rabbit").must_be_nil
182
+ end
183
+ end
184
+
185
+ it "reads multiple keys" do
186
+ @store.write "irish whisky", "Jameson"
187
+ result = @store.read_multi "rabbit", "irish whisky"
188
+ result['rabbit'].must_equal(@rabbit)
189
+ result['irish whisky'].must_equal("Jameson")
190
+ end
191
+
192
+ it "reads multiple keys and returns only the matched ones" do
193
+ @store.delete 'irish whisky'
194
+ result = @store.read_multi "rabbit", "irish whisky"
195
+ result.wont_include('irish whisky')
196
+ result.must_include('rabbit')
197
+ end
198
+
199
+ describe "notifications" do
200
+ it "notifies on #fetch" do
201
+ with_notifications do
202
+ @store.fetch("radiohead") { "House Of Cards" }
203
+ end
204
+
205
+ read, generate, write = @events
206
+
207
+ read.name.must_equal('cache_read.active_support')
208
+ read.payload.must_equal({ :key => 'radiohead', :super_operation => :fetch })
209
+
210
+ generate.name.must_equal('cache_generate.active_support')
211
+ generate.payload.must_equal({ :key => 'radiohead' })
212
+
213
+ write.name.must_equal('cache_write.active_support')
214
+ write.payload.must_equal({ :key => 'radiohead' })
215
+ end
216
+
217
+ it "notifies on #read" do
218
+ with_notifications do
219
+ @store.read "metallica"
220
+ end
221
+
222
+ read = @events.first
223
+ read.name.must_equal('cache_read.active_support')
224
+ read.payload.must_equal({ :key => 'metallica', :hit => false })
225
+ end
226
+
227
+ it "notifies on #write" do
228
+ with_notifications do
229
+ @store.write "depeche mode", "Enjoy The Silence"
230
+ end
231
+
232
+ write = @events.first
233
+ write.name.must_equal('cache_write.active_support')
234
+ write.payload.must_equal({ :key => 'depeche mode' })
235
+ end
236
+
237
+ it "notifies on #delete" do
238
+ with_notifications do
239
+ @store.delete "the new cardigans"
240
+ end
241
+
242
+ delete = @events.first
243
+ delete.name.must_equal('cache_delete.active_support')
244
+ delete.payload.must_equal({ :key => 'the new cardigans' })
245
+ end
246
+
247
+ it "notifies on #exist?" do
248
+ with_notifications do
249
+ @store.exist? "the smiths"
250
+ end
251
+
252
+ exist = @events.first
253
+ exist.name.must_equal('cache_exist?.active_support')
254
+ exist.payload.must_equal({ :key => 'the smiths' })
255
+ end
256
+
257
+ it "notifies on #delete_matched" do
258
+ with_notifications do
259
+ @store.delete_matched "afterhours*"
260
+ end
261
+
262
+ delete_matched = @events.first
263
+ delete_matched.name.must_equal('cache_delete_matched.active_support')
264
+ delete_matched.payload.must_equal({ :key => %("afterhours*") })
265
+ end
266
+
267
+ it "notifies on #increment" do
268
+ with_notifications do
269
+ @store.increment "pearl jam"
270
+ end
271
+
272
+ increment = @events.first
273
+ increment.name.must_equal('cache_increment.active_support')
274
+ increment.payload.must_equal({ :key => 'pearl jam', :amount => 1 })
275
+ end
276
+
277
+ it "notifies on #decrement" do
278
+ with_notifications do
279
+ @store.decrement "placebo"
280
+ end
281
+
282
+ decrement = @events.first
283
+ decrement.name.must_equal('cache_decrement.active_support')
284
+ decrement.payload.must_equal({ :key => 'placebo', :amount => 1 })
285
+ end
286
+
287
+ # it "notifies on cleanup" # TODO implement in ActiveSupport::Cache::RedisStore
288
+
289
+ it "should notify on clear" do
290
+ with_notifications do
291
+ @store.clear
292
+ end
293
+
294
+ clear = @events.first
295
+ clear.name.must_equal('cache_clear.active_support')
296
+ clear.payload.must_equal({ :key => nil })
297
+ end
298
+ end
299
+
300
+ private
301
+ def instantiate_store(addresses = nil)
302
+ ActiveSupport::Cache::RedisStore.new(addresses).instance_variable_get(:@data)
303
+ end
304
+
305
+ def with_store_management
306
+ yield @store
307
+ yield @dstore
308
+ end
309
+
310
+ def with_notifications
311
+ @events = [ ]
312
+ ActiveSupport::Cache::RedisStore.instrument = true
313
+ ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args|
314
+ @events << ActiveSupport::Notifications::Event.new(*args)
315
+ end
316
+ yield
317
+ ActiveSupport::Cache::RedisStore.instrument = false
318
+ end
319
+ end
320
+
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ describe Redis::ActiveSupport::VERSION do
4
+ it 'returns current version' do
5
+ Redis::ActiveSupport::VERSION.must_equal '4.0.0'
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'mocha/setup'
4
+ require 'active_support'
5
+ require 'active_support/cache/redis_store'
6
+
metadata ADDED
@@ -0,0 +1,175 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fault_tolerant_redis-activesupport
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Luca Guidi
8
+ - Jan Renra Gloser
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-11-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis-store
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 1.1.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 1.1.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: activesupport
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '4'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '4'
42
+ - !ruby/object:Gem::Dependency
43
+ name: maybe_client
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '='
47
+ - !ruby/object:Gem::Version
48
+ version: 1.1.0
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 1.1.0
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10'
70
+ - !ruby/object:Gem::Dependency
71
+ name: bundler
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1.3'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '1.3'
84
+ - !ruby/object:Gem::Dependency
85
+ name: mocha
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: 0.14.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: 0.14.0
98
+ - !ruby/object:Gem::Dependency
99
+ name: minitest
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '4.2'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '4.2'
112
+ - !ruby/object:Gem::Dependency
113
+ name: redis-store-testing
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: Fault tolerant redis store for ActiveSupport
127
+ email:
128
+ - me@lucaguidi.com
129
+ - jan.renra.gloser@gmail.com
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".env"
135
+ - ".gitignore"
136
+ - ".travis.yml"
137
+ - Gemfile
138
+ - MIT-LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - fault_tolerant_redis-activesupport.gemspec
142
+ - lib/active_support/cache/fault_tolerant_redis_store.rb
143
+ - lib/fault_tolerant_redis-activesupport.rb
144
+ - lib/redis/activesupport/version.rb
145
+ - test/active_support/cache/redis_store_test.rb
146
+ - test/redis/activesupport/version_test.rb
147
+ - test/test_helper.rb
148
+ homepage: https://github.com/renra/redis-activesupport
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project: redis-activesupport
168
+ rubygems_version: 2.4.5.1
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: Fault tolerant redis store for ActiveSupport
172
+ test_files:
173
+ - test/active_support/cache/redis_store_test.rb
174
+ - test/redis/activesupport/version_test.rb
175
+ - test/test_helper.rb