stockpile-redis 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5265acd0adce155a74ad5e760a4220f2e67d21bd
4
+ data.tar.gz: a0255909976359af85261d59d10b9b7cf50fc256
5
+ SHA512:
6
+ metadata.gz: f4bcc22097af1e9ecda717d747a8462da5b7894ec795a27878a6f3bd44d6bd65eddba590b24f00064f20315f8f7be5bf6c44f5633f48824a620b431ab18a6880
7
+ data.tar.gz: 5878c2e4459ad15f96b65948d2b724c0bd7062dbe63d44db9b1329edb661558d7297f391c6540d328e3d130674ac860698fef53d46dc48f9534d87be90615c9b
@@ -0,0 +1,27 @@
1
+ # -*- ruby -*-
2
+
3
+ require "autotest/restart"
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ # .minitest.rb ensures that the gem version of minitest is used.
7
+ at.testlib = ".minitest.rb"
8
+ # at.testlib = "minitest/unit"
9
+ #
10
+ # at.extra_files << "../some/external/dependency.rb"
11
+ #
12
+ # at.libs << ":../some/external"
13
+ #
14
+ # at.add_exception "vendor"
15
+ #
16
+ # at.add_mapping(/dependency.rb/) do |f, _|
17
+ # at.files_matching(/test_.*rb$/)
18
+ # end
19
+ #
20
+ # %w(TestA TestB).each do |klass|
21
+ # at.extra_class_map[klass] = "test/test_misc.rb"
22
+ # end
23
+ end
24
+
25
+ # Autotest.add_hook :run_command do |at|
26
+ # system "rake build"
27
+ # end
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,2 @@
1
+ gem "minitest"
2
+ require "minitest/autorun"
@@ -0,0 +1,37 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - "2.2"
5
+ - "2.1"
6
+ - 2.0.0
7
+ - 1.9.3
8
+ - ruby-head
9
+ - jruby-19mode
10
+ - jruby-head
11
+ - rbx-2
12
+ matrix:
13
+ allow_failures:
14
+ - rvm: rbx-2
15
+ - rvm: jruby-head
16
+ - rvm: ruby-head
17
+ gemfile:
18
+ - Gemfile
19
+ before_script:
20
+ - |
21
+ case "${TRAVIS_RUBY_VERSION}" in
22
+ rbx*)
23
+ gem install psych
24
+ ;;
25
+ esac
26
+ - rake travis:before -t
27
+ script: rake travis
28
+ after_script:
29
+ - rake travis:after -t
30
+ notifications:
31
+ email:
32
+ recipients:
33
+ - halostatue@gmail.com
34
+ on_success: change
35
+ on_failure: always
36
+ sudo:
37
+ false
@@ -0,0 +1,5 @@
1
+ #! zsh
2
+
3
+ --workenv-tab --first
4
+ --workenv-tab --desc autotest autotest
5
+ --workenv-tab --desc documents "fswatch -o *.rdoc lib/**/*.rb| xargs -n1 -I{} rake docs"
@@ -0,0 +1,64 @@
1
+ == Contributing
2
+
3
+ I value any contribution to stockpile-redis you can provide: a bug report, a
4
+ feature request, or code contributions.
5
+
6
+ As stockpile-redis is a complex codebase, there are a few guidelines:
7
+
8
+ * Changes *will* *not* be accepted without tests. The test suite is written
9
+ with {Minitest}[https://github.com/seattlerb/minitest].
10
+ * Match my coding style.
11
+ * Use a thoughtfully-named topic branch that contains your change. Rebase your
12
+ commits into logical chunks as necessary.
13
+ * Use {quality commit messages}[http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html].
14
+ * Do not change the version number; when your patch is accepted and a release
15
+ is made, the version will be updated at that point.
16
+ * Submit a GitHub pull request with your changes.
17
+ * New behaviours require new or updated documentation.
18
+
19
+ === Test Dependencies
20
+
21
+ stockpile-redis uses Ryan Davis’s {Hoe}[https://github.com/seattlerb/hoe]
22
+ to manage the release process, and it adds a number of rake tasks. You will
23
+ mostly be interested in:
24
+
25
+ $ rake
26
+
27
+ which runs the tests the same way that:
28
+
29
+ $ rake test
30
+ $ rake travis
31
+
32
+ will do.
33
+
34
+ To assist with the installation of the development dependencies for
35
+ stockpile-redis, I have provided the simplest possible Gemfile pointing to
36
+ the (generated) +stockpile-redis.gemspec+ file. This will permit you to do:
37
+
38
+ $ bundle install
39
+
40
+ to get the development dependencies. If you aleady have +hoe+ installed, you
41
+ can accomplish the same thing with:
42
+
43
+ $ rake newb
44
+
45
+ This task will install any missing dependencies, run the tests/specs, and
46
+ generate the RDoc.
47
+
48
+ === Workflow
49
+
50
+ Here's the most direct way to get your work merged into the project:
51
+
52
+ * Fork the project.
53
+ * Clone down your fork (<tt>git clone git://github.com/halostatue/stockpile-redis.git</tt>).
54
+ * Create a topic branch to contain your change (<tt>git checkout -b my\_awesome\_feature</tt>).
55
+ * Hack away, add tests. Not necessarily in that order.
56
+ * Make sure everything still passes by running +rake+.
57
+ * If necessary, rebase your commits into logical chunks, without errors.
58
+ * Push the branch up (<tt>git push origin my\_awesome\_feature</tt>).
59
+ * Create a pull request against halostatue/stockpile-redis and describe
60
+ what your change does and the why you think it should be merged.
61
+
62
+ === Contributors
63
+
64
+ * Austin Ziegler created stockpile-redis.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # -*- ruby -*-
2
+
3
+ # NOTE: This file is present to keep Travis CI happy. Edits to it will not
4
+ # be accepted.
5
+
6
+ source "https://rubygems.org/"
7
+ gemspec
8
+
9
+ # vim: syntax=ruby
@@ -0,0 +1,5 @@
1
+ === 1.0 / 2015-01-21
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
@@ -0,0 +1,27 @@
1
+ == Licence
2
+
3
+ This software is available under an MIT-style licence.
4
+
5
+ * Copyright 2015 Austin Ziegler
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ this software and associated documentation files (the "Software"), to deal in
9
+ the Software without restriction, including without limitation the rights to
10
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11
+ of the Software, and to permit persons to whom the Software is furnished to do
12
+ so, subject to the following conditions:
13
+
14
+ * The names of its contributors may not be used to endorse or promote
15
+ products derived from this software without specific prior written
16
+ permission.
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
@@ -0,0 +1,17 @@
1
+ .autotest
2
+ .gemtest
3
+ .minitest.rb
4
+ .travis.yml
5
+ .workenv
6
+ Contributing.rdoc
7
+ Gemfile
8
+ History.rdoc
9
+ Licence.rdoc
10
+ Manifest.txt
11
+ README.rdoc
12
+ Rakefile
13
+ lib/stockpile-redis.rb
14
+ lib/stockpile/redis.rb
15
+ test/minitest_config.rb
16
+ test/test_stockpile_adapter_redis.rb
17
+ test/test_stockpile_redis.rb
@@ -0,0 +1,118 @@
1
+ = stockpile-redis
2
+
3
+ code :: https://github.com/halostatue/stockpile-redis/
4
+ bugs :: https://github.com/halostatue/stockpile-redis/issues
5
+ continuous integration :: {<img src="https://travis-ci.org/halostatue/stockpile-redis.png" />}[https://travis-ci.org/halostatue/stockpile-redis]
6
+
7
+ == Description
8
+
9
+ stockpile-redis is a connection manager for Redis to be used with
10
+ {Stockpile}[https://github.com/halostatue/stockpile].
11
+
12
+ == Features
13
+
14
+ stockpile-redis supports both normal Redis connections (<tt>Redis.new</tt>),
15
+ and Redis::Namespace connections (<tt>Redis::Namespace.new('namespace', redis:
16
+ Redis.new</tt>).
17
+
18
+ stockpile-redis provides special-case handling for connections for Resque when
19
+ the name of the client is +:resque+.
20
+
21
+ == Synopsis
22
+
23
+ require 'stockpile/redis'
24
+
25
+ wide = Stockpile.new(manager: Stockpile::Redis) # A Stockpile to Redis.
26
+ wide.connection.set('hello', 'world') # => 'OK'
27
+ wide.connection.get('hello') # => 'world'
28
+
29
+ # Connections are independent from one another.
30
+ wide.connection_for(:other) != wide.connection # => true
31
+
32
+ # A 'narrow' Stockpile to Redis.
33
+ narrow = Stockpile.new(manager: Stockpile::Redis, narrow: true)
34
+ # Or set ENV['STOCKPILE_CONNECTION_WIDTH'] = 'narrow' and call Stockpile.new
35
+ # normally.
36
+ narrow.connection_for(:other) == narrow.connection # => true
37
+
38
+ # Special Redis::Namespace handling for Resque clients.
39
+ narrow.connection_for(:resque) != narrow.connection # => true
40
+ narrow.connection_for(:resque).redis == narrow.connection # => true
41
+
42
+ # Show a Stockpile with no adapter capabilities, but name the method
43
+ # stockpile, not cache. This will still usefully manage connections.
44
+ # The use of inject_redis! makes Stockpile::Redis the default connection
45
+ # manager for the Cacher module Stockpile.
46
+ module Cacher
47
+ Stockpile.inject_redis!(self, method: :stockpile, adaptable: false)
48
+ end
49
+ Cacher.respond_to?(:stockpile) # => true
50
+ Cacher.respond_to?(:stockpile_adapter) # => false
51
+ Cacher.stockpile.connection.set('hello', 'world') # => 'OK'
52
+ Cacher.stockpile.connection.get('hello') # => 'world'
53
+
54
+ # Now a Stockpile with adapter capabilities.
55
+ module Jobber
56
+ module LastRunTime
57
+ def last_run_time(key, value = nil)
58
+ if value
59
+ connection.hset(__method__, key, value.utc.iso8601)
60
+ else
61
+ value = connection.hget(__method__, key)
62
+ Time.parse(value) if value
63
+ end
64
+ end
65
+ end
66
+
67
+ Stockpile.inject_redis!(self)
68
+ end
69
+ Jobber.respond_to?(:cache) # => true
70
+ Jobber.respond_to?(:cache_adapter) # => true
71
+
72
+ # Four ways:
73
+ # 1. Adapt Jobber.cache to recognize #last_run_time.
74
+ Jobber.cache_adapter(Jobber::LastRunTime)
75
+ Jobber.cache.last_run_time('hello', t = Time.now) # => true
76
+ Jobber.cache.last_run_time('hello') # => approximately t
77
+
78
+ # 2. Adapt Jobber.cache and another module to recognize #last_run_time.
79
+ module Foo; end
80
+ Jobber.cache_adapter(Jobber::LastRunTime, Foo)
81
+ Foo.last_run_time('hello', t = Time.now) # => true
82
+ Foo.last_run_time('hello') # => approximately t
83
+
84
+ # 3. Adapt Jobber.cache and Jobber to recognize #last_run_time.
85
+ Jobber.cache_adapter(Jobber::LastRunTime, Jobber)
86
+ Jobber.last_run_time('hello', t = Time.now) # => true
87
+ Jobber.last_run_time('hello') # => approximately t
88
+
89
+ # 4. Adapt Jobber.cache and Jobber::LastRunTime to recognize #last_run_time.
90
+ Jobber.cache_adapter!(Jobber::LastRunTime)
91
+ # or Jobber.cache_adapter(Jobber::LastRunTime, Jobber::LastRunTime)
92
+ Jobber::LastRunTime.last_run_time('hello', t = Time.now) # => true
93
+ Jobber::LastRunTime.last_run_time('hello') # => approximately t
94
+
95
+ == Install
96
+
97
+ Put stockpile-redis in your Gemfile:
98
+
99
+ gem 'stockpile-redis', '~> 1.0'
100
+
101
+ Or manually install:
102
+
103
+ % gem install stockpile-redis
104
+
105
+ and require Stockpile in your code:
106
+
107
+ require 'stockpile/redis'
108
+
109
+ == stockpile-redis Semantic Versioning
110
+
111
+ stockpile-redis uses a {Semantic Versioning}[http://semver.org/] scheme with
112
+ one change:
113
+
114
+ * When PATCH is zero (+0+), it will be omitted from version references.
115
+
116
+ :include: Contributing.rdoc
117
+
118
+ :include: Licence.rdoc
@@ -0,0 +1,56 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :doofus
7
+ Hoe.plugin :gemspec2
8
+ Hoe.plugin :git
9
+ Hoe.plugin :minitest
10
+ Hoe.plugin :travis
11
+ Hoe.plugin :email unless ENV['CI'] or ENV['TRAVIS']
12
+
13
+ spec = Hoe.spec 'stockpile-redis' do
14
+ developer('Austin Ziegler', 'halostatue@gmail.com')
15
+
16
+ self.history_file = 'History.rdoc'
17
+ self.readme_file = 'README.rdoc'
18
+ self.extra_rdoc_files = FileList["*.rdoc"].to_a
19
+
20
+ license "MIT"
21
+
22
+ self.need_tar = true
23
+ self.require_ruby_version '>= 1.9.2'
24
+
25
+ self.extra_deps << ['stockpile', '~> 1.0']
26
+ self.extra_deps << ['redis', '~> 3.0']
27
+ self.extra_deps << ['redis-namespace', '~> 1.0']
28
+ self.extra_dev_deps << ['fakeredis', '~> 0.5']
29
+ self.extra_dev_deps << ['hoe-doofus', '~> 1.0']
30
+ self.extra_dev_deps << ['hoe-gemspec2', '~> 1.1']
31
+ self.extra_dev_deps << ['hoe-git', '~> 1.5']
32
+ self.extra_dev_deps << ['hoe-travis', '~> 1.2']
33
+ self.extra_dev_deps << ['minitest', '~> 5.4']
34
+ self.extra_dev_deps << ['minitest-around', '~> 0.3']
35
+ self.extra_dev_deps << ['minitest-autotest', '~> 1.0']
36
+ self.extra_dev_deps << ['minitest-bisect', '~> 1.2']
37
+ self.extra_dev_deps << ['minitest-focus', '~> 1.1']
38
+ self.extra_dev_deps << ['minitest-moar', '~> 0.0']
39
+ self.extra_dev_deps << ['minitest-pretty_diff', '~> 0.1']
40
+ self.extra_dev_deps << ['rake', '>= 10.0']
41
+ self.extra_dev_deps << ['redis-namespace', '~> 1.5']
42
+ self.extra_dev_deps << ['simplecov', '~> 0.7']
43
+ end
44
+
45
+ namespace :test do
46
+ task :coverage do
47
+ spec.test_prelude = [
48
+ 'require "simplecov"',
49
+ 'SimpleCov.start("test_frameworks") { command_name "Minitest" }',
50
+ 'gem "minitest"'
51
+ ].join('; ')
52
+ Rake::Task['test'].execute
53
+ end
54
+ end
55
+
56
+ # vim: syntax=ruby
@@ -0,0 +1 @@
1
+ require 'stockpile/redis'
@@ -0,0 +1,195 @@
1
+ # coding: utf-8
2
+
3
+ require 'redis'
4
+ require 'redis/namespace'
5
+ require 'stockpile'
6
+
7
+ class Stockpile
8
+ # A connection manager for Redis.
9
+ class Redis
10
+ VERSION = '1.0' # :nodoc:
11
+
12
+ # Create a new Redis connection manager with the provided options.
13
+ #
14
+ # == Options
15
+ #
16
+ # +redis+:: Provides the Redis connection options.
17
+ # +namespace+:: Provides the Redis namespace to use, but only if
18
+ # redis-namespace is in use (detected with the existence of
19
+ # Redis::Namespace).
20
+ #
21
+ # The namespace can also be provided as a key in the +redis+
22
+ # options if it is missing from the main options. If there is
23
+ # no namespace key present in either +options+ or
24
+ # <tt>options[:redis]</tt>, a namespace will be generated
25
+ # from one of the following: <tt>$REDIS_NAMESPACE</tt>,
26
+ # <tt>Rails.env</tt> (if in Rails), or <tt>$RACK_ENV</tt>.
27
+ # +narrow+:: Use a narrow connection width if true; if not provided,
28
+ # uses the value of ::Stockpile.narrow? in this connection
29
+ # manager.
30
+ def initialize(options = {})
31
+ @redis_options = options.fetch(:redis, {})
32
+ @narrow = !!options.fetch(:narrow, ::Stockpile.narrow?)
33
+ @namespace = options.fetch(:namespace) {
34
+ @redis_options.fetch(:namespace) {
35
+ ENV['REDIS_NAMESPACE'] ||
36
+ (defined?(::Rails) && ::Rails.env) ||
37
+ ENV['RACK_ENV']
38
+ }
39
+ }
40
+
41
+ if @redis_options.has_key?(:namespace)
42
+ @redis_options = @redis_options.reject { |k, _| k == :namespace }
43
+ end
44
+
45
+ @connection = nil
46
+ @clients = {}
47
+ end
48
+
49
+ # The current primary connection to Redis.
50
+ attr_reader :connection
51
+
52
+ # Indicates if this connection manager is using a narrow connection
53
+ # width.
54
+ def narrow?
55
+ @narrow
56
+ end
57
+
58
+ # Connect to Redis, unless already connected. Additional client connections
59
+ # can be specified in the parameters as a shorthand for calls to
60
+ # #connection_for.
61
+ #
62
+ # If #narrow? is true, the same Redis connection will be used for all
63
+ # clients managed by this connection manager.
64
+ #
65
+ # manager.connect
66
+ # manager.connection_for(:redis)
67
+ #
68
+ # # This means the same as above.
69
+ # manager.connect(:redis)
70
+ def connect(*client_names)
71
+ @connection ||= connect_for_any
72
+
73
+ clients_from(*client_names).each { |client_name|
74
+ connection_for(client_name)
75
+ }
76
+
77
+ connection
78
+ end
79
+
80
+ # Perform a client connection to Redis for a specific +client_name+. The
81
+ # +client_name+ of +:all+ will always return +nil+.
82
+ #
83
+ # If the requested client does not yet exist, the connection will be
84
+ # created.
85
+ #
86
+ # Because Resque depends on Redis::Namespace, #connection_for will perform
87
+ # special Redis::Namespace handling for a connection with the name
88
+ # +:resque+.
89
+ #
90
+ # If #narrow? is true, the same Redis connection will be shared between all
91
+ # clients.
92
+ #
93
+ # If a connection has not yet been made, it will be made.
94
+ def connection_for(client_name)
95
+ connect unless connection
96
+ return nil if client_name == :all
97
+ @clients[client_name] ||= case client_name
98
+ when :resque
99
+ connect_for_resque
100
+ else
101
+ connect_for_any
102
+ end
103
+ end
104
+
105
+ # Reconnect to Redis for some or all clients. The primary connection will
106
+ # always be reconnected; other clients will be reconnected based on the
107
+ # +clients+ provided. Only clients actively managed by previous calls to
108
+ # #connect or #connection_for will be reconnected.
109
+ #
110
+ # If #reconnect is called with the value +:all+, all currently managed
111
+ # clients will be reconnected.
112
+ #
113
+ # If #narrow? is true, only the primary connection will be reconnected.
114
+ def reconnect(*client_names)
115
+ return unless connection
116
+
117
+ connection.client.reconnect
118
+
119
+ unless narrow?
120
+ clients_from(*client_names).each { |client_name|
121
+ redis = @clients[client_name]
122
+ redis.client.reconnect if redis
123
+ }
124
+ end
125
+
126
+ connection
127
+ end
128
+
129
+ # Disconnect from Redis for some or all clients. The primary connection
130
+ # will always be disconnected; other clients will be disconnected based on
131
+ # the +clients+ provided. Only clients actively managed by previous calls
132
+ # to #connect or #connection_for will be disconnected.
133
+ #
134
+ # If #disconnect is called with the value +:all+, all currently managed
135
+ # clients will be disconnected.
136
+ #
137
+ # If #narrow? is true, only the primary connection will be disconnected.
138
+ def disconnect(*client_names)
139
+ return unless connection
140
+
141
+ unless narrow?
142
+ clients_from(*client_names).each { |client_name|
143
+ redis = @clients[client_name]
144
+ redis.quit if redis
145
+ }
146
+ end
147
+
148
+ connection.quit
149
+ end
150
+
151
+ private
152
+ def clients_from(*client_names)
153
+ if client_names.size == 1
154
+ if client_names.first == :all
155
+ @clients.keys
156
+ else
157
+ client_names
158
+ end
159
+ else
160
+ client_names
161
+ end
162
+ end
163
+
164
+ def connect_for_any
165
+ return connection if connection && narrow?
166
+
167
+ r = ::Redis.new(@redis_options)
168
+ if @namespace
169
+ r = ::Redis::Namespace.new(@namespace, redis: r)
170
+ end
171
+ r
172
+ end
173
+
174
+ def connect_for_resque
175
+ r = connect_for_any
176
+
177
+ if r.instance_of?(::Redis::Namespace) && r.namespace.to_s !~ /:resque\z/
178
+ r = ::Redis::Namespace.new(:"#{r.namespace}:resque", redis: r.redis)
179
+ elsif r.instance_of?(::Redis)
180
+ r = ::Redis::Namespace.new("resque", redis: r)
181
+ end
182
+
183
+ r
184
+ end
185
+ end
186
+
187
+ # Enables module or class +mod+ to contain a Stockpile instance that defaults
188
+ # the created +cache+ method to using Stockpile::Redis as the key-value store
189
+ # connection manager.
190
+ #
191
+ # See <tt>Stockpile.inject!</tt>.
192
+ def self.inject_redis!(mod, options = {})
193
+ inject!(mod, options.merge(default_manager: Stockpile::Redis))
194
+ end
195
+ end
@@ -0,0 +1,41 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ gem 'minitest'
4
+ require 'minitest/autorun'
5
+ require 'minitest/pretty_diff'
6
+ require 'minitest/focus'
7
+ require 'minitest/moar'
8
+ require 'minitest/bisect'
9
+
10
+ require 'fakeredis'
11
+
12
+ module Minitest::FakeRedis
13
+ def setup
14
+ super
15
+ Redis::Connection::Memory.reset_all_databases
16
+ end
17
+
18
+ Minitest::Test.send(:include, self)
19
+ end
20
+
21
+ module Minitest::ENVStub
22
+ def stub_env env, options = {}, *block_args, &block
23
+ mock = lambda { |key|
24
+ env.fetch(key) { |k|
25
+ if options[:passthrough]
26
+ ENV.send(:"__minitest_stub__[]", k)
27
+ else
28
+ nil
29
+ end
30
+ }
31
+ }
32
+
33
+ if defined? Minitest::Moar::Stubbing
34
+ stub ENV, :[], mock, *block_args, &block
35
+ else
36
+ ENV.stub :[], mock, *block_args, &block
37
+ end
38
+ end
39
+
40
+ Minitest::Test.send(:include, self)
41
+ end
@@ -0,0 +1,47 @@
1
+ require 'minitest_config'
2
+ require 'stockpile/redis'
3
+ require 'time'
4
+
5
+ describe Stockpile do
6
+ describe ".inject!" do
7
+ let(:mod) { Module.new }
8
+ let(:lrt) {
9
+ Module.new do
10
+ def last_run_time(key, value = nil)
11
+ if value
12
+ connection.hset(__method__, key, value.utc.iso8601)
13
+ else
14
+ value = connection.hget(__method__, key)
15
+ Time.parse(value) if value
16
+ end
17
+ end
18
+ end
19
+ }
20
+
21
+ describe "Mod.cache_adapter" do
22
+ let(:now) { Time.now }
23
+ before { ::Stockpile.inject_redis!(mod, adaptable: true) }
24
+
25
+ it "adapts the cache with last_run_time" do
26
+ mod.cache_adapter(lrt)
27
+ assert_nil mod.cache.last_run_time('foo')
28
+ assert_equal true, mod.cache.last_run_time('foo', now)
29
+ assert_equal now.to_i, mod.cache.last_run_time('foo').to_i
30
+ end
31
+
32
+ it "adapts the module with last_run_time" do
33
+ mod.cache_adapter(lrt, mod)
34
+ assert_nil mod.last_run_time('foo')
35
+ assert_equal true, mod.last_run_time('foo', now)
36
+ assert_equal now.to_i, mod.last_run_time('foo').to_i
37
+ end
38
+
39
+ it "adapts the lrt module with last_run_time" do
40
+ mod.cache_adapter!(lrt)
41
+ assert_nil lrt.last_run_time('foo')
42
+ assert_equal true, lrt.last_run_time('foo', now)
43
+ assert_equal now.to_i, lrt.last_run_time('foo').to_i
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,281 @@
1
+ require 'minitest_config'
2
+ require 'stockpile/redis'
3
+
4
+ describe Stockpile::Redis do
5
+ def assert_clients expected_clients, connector
6
+ actual_clients = connector.instance_variable_get(:@clients).keys
7
+ assert_equal actual_clients.sort, expected_clients.sort
8
+ end
9
+
10
+ let(:rcm) { stub_env({}) { Stockpile::Redis.new } }
11
+ let(:rcm_namespace) { stub_env({}) { Stockpile::Redis.new(namespace: 'Z') } }
12
+ let(:rcm_wide) { stub_env({}) { Stockpile::Redis.new(narrow: false) } }
13
+ let(:rcm_narrow) { stub_env({}) { Stockpile::Redis.new(narrow: true) } }
14
+
15
+ describe 'constructor' do
16
+ it "uses the default connection width by default" do
17
+ stub ::Stockpile, :narrow?, lambda { false } do
18
+ refute Stockpile::Redis.new.narrow?,
19
+ "should be narrow, but is not"
20
+ end
21
+
22
+ stub ::Stockpile, :narrow?, lambda { true } do
23
+ assert Stockpile::Redis.new.narrow?,
24
+ "is not narrow, but should be"
25
+ end
26
+ end
27
+
28
+ it "can be told which connection width to use explicitly" do
29
+ stub ::Stockpile, :narrow?, lambda { false } do
30
+ assert rcm_narrow.narrow?
31
+ end
32
+
33
+ stub ::Stockpile, :narrow?, lambda { true } do
34
+ refute rcm_wide.narrow?
35
+ end
36
+ end
37
+
38
+ it "passes settings through to Redis" do
39
+ options = {
40
+ redis: {
41
+ url: 'redis://xyz/'
42
+ }
43
+ }
44
+ rcm = ::Stockpile::Redis.new(options)
45
+ assert_equal 'xyz', rcm.connect.client.options[:host]
46
+ end
47
+
48
+ it "has no clients by default" do
49
+ assert_clients [], ::Stockpile::Redis.new
50
+ end
51
+
52
+ describe "namespace support" do
53
+ def assert_namespace(client)
54
+ assert_equal 'stockpile', client.instance_variable_get(:@namespace)
55
+ end
56
+
57
+ it "will set namespace from ENV['REDIS_NAMESPACE']" do
58
+ stub_env({ 'REDIS_NAMESPACE' => 'stockpile' }) do
59
+ assert_namespace ::Stockpile::Redis.new
60
+ end
61
+ end
62
+
63
+ it "will set namespace from Rails.env" do
64
+ begin
65
+ ::Rails = Class.new do
66
+ def self.env
67
+ 'stockpile'
68
+ end
69
+ end
70
+
71
+ stub_env({}) do
72
+ assert_namespace ::Stockpile::Redis.new
73
+ end
74
+ ensure
75
+ Object.send(:remove_const, :Rails)
76
+ end
77
+ end
78
+
79
+ it "will set namespace from ENV['RACK_ENV']" do
80
+ stub_env({ 'RACK_ENV' => 'stockpile' }) do
81
+ assert_namespace ::Stockpile::Redis.new
82
+ end
83
+ end
84
+
85
+ it "will set namespace from parameters" do
86
+ stub_env({ 'RACK_ENV' => 'test' }) do
87
+ assert_namespace ::Stockpile::Redis.new(namespace: 'stockpile')
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#connect" do
94
+ it "creates a connection to Redis" do
95
+ assert_nil rcm.connection
96
+ refute_nil rcm.connect
97
+ assert_kind_of ::Redis, rcm.connection
98
+ end
99
+
100
+ it "creates a namespaced connection to Redis" do
101
+ assert_nil rcm_namespace.connection
102
+ refute_nil rcm_namespace.connect
103
+ assert_kind_of ::Redis::Namespace, rcm_namespace.connection
104
+ end
105
+
106
+ describe "with a wide connection width" do
107
+ before do
108
+ rcm_wide.connect(:redis, :rollout)
109
+ end
110
+
111
+ it "connects multiple clients" do
112
+ assert_clients [ :redis, :rollout ], rcm_wide
113
+ end
114
+
115
+ it "connects *different* clients" do
116
+ refute_same rcm_wide.connection, rcm_wide.connection_for(:redis)
117
+ refute_same rcm_wide.connection, rcm_wide.connection_for(:rollout)
118
+ refute_same rcm_wide.connection_for(:redis), rcm_wide.connection_for(:rollout)
119
+ end
120
+ end
121
+
122
+ describe "with a narrow connection width" do
123
+ before do
124
+ rcm_narrow.connect(:redis, :rollout)
125
+ end
126
+
127
+ it "appears to connect multiple clients" do
128
+ assert_clients [ :redis, :rollout ], rcm_narrow
129
+ end
130
+
131
+ it "returns identical clients" do
132
+ assert_same rcm_narrow.connection, rcm_narrow.connection_for(:redis)
133
+ assert_same rcm_narrow.connection, rcm_narrow.connection_for(:rollout)
134
+ assert_same rcm_narrow.connection_for(:redis), rcm_narrow.connection_for(:rollout)
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "#connection_for" do
140
+ describe "with a wide connection width" do
141
+ it "connects the main client" do
142
+ rcm_wide.connection_for(:global)
143
+ assert rcm_wide.connection
144
+ refute_same rcm_wide.connection, rcm_wide.connection_for(:global)
145
+ end
146
+
147
+ it "wraps a :resque client in Redis::Namespace" do
148
+ assert_kind_of Redis::Namespace, rcm_wide.connection_for(:resque)
149
+ assert_equal "resque", rcm_wide.connection_for(:resque).namespace
150
+ end
151
+ end
152
+
153
+ describe "with a narrow connection width" do
154
+ it "connects the main client" do
155
+ rcm_narrow.connection_for(:global)
156
+ assert rcm_narrow.connection
157
+ assert_same rcm_narrow.connection, rcm_narrow.connection_for(:global)
158
+ end
159
+
160
+ it "wraps a :resque client in Redis::Namespace" do
161
+ assert_kind_of Redis::Namespace, rcm_narrow.connection_for(:resque)
162
+ end
163
+ end
164
+ end
165
+
166
+ # #disconnect cannot be tested with FakeRedis because the FakeRedis
167
+ # #connected? method always returns true.
168
+ describe "#disconnect" do
169
+ describe "with a wide connection width" do
170
+ let(:global) { rcm_wide.connection }
171
+ let(:redis) { rcm_wide.connection_for(:redis) }
172
+
173
+ def force_connection
174
+ rcm_wide.connect(:redis)
175
+ global.client.connect
176
+ redis.client.connect
177
+ end
178
+
179
+ it "disconnects the global client" do
180
+ instance_stub Redis, :quit do
181
+ force_connection
182
+ rcm_wide.disconnect
183
+ end
184
+ assert_instance_called Redis, :quit, 1
185
+ end
186
+
187
+ it "disconnects the redis and global clients" do
188
+ instance_stub Redis, :quit do
189
+ force_connection
190
+ rcm_wide.disconnect(:redis)
191
+ end
192
+ assert_instance_called Redis, :quit, 2
193
+ end
194
+ end
195
+
196
+ describe "with a narrow connection width" do
197
+ let(:global) { rcm_narrow.connection }
198
+ let(:redis) { rcm_narrow.connection_for(:redis) }
199
+
200
+ def force_connection
201
+ rcm_narrow.connect(:redis)
202
+ global.client.connect
203
+ redis.client.connect
204
+ end
205
+
206
+ it "disconnects the global client" do
207
+ instance_stub Redis, :quit do
208
+ force_connection
209
+ rcm_narrow.disconnect
210
+ end
211
+ assert_instance_called Redis, :quit, 1
212
+ end
213
+
214
+ it "disconnects the redis and global clients" do
215
+ instance_stub Redis, :quit do
216
+ force_connection
217
+ rcm_narrow.disconnect(:redis)
218
+ end
219
+ assert_instance_called Redis, :quit, 1
220
+ end
221
+ end
222
+ end
223
+
224
+ # #reconnect cannot be tested with FakeRedis because the FakeRedis
225
+ # #connected? method always returns true.
226
+ describe "#reconnect" do
227
+ describe "with a wide connection width" do
228
+ let(:global) { rcm_wide.connection }
229
+ let(:redis) { rcm_wide.connection_for(:redis) }
230
+
231
+ def force_connection
232
+ rcm_wide.connect(:redis)
233
+ global.client.connect
234
+ redis.client.connect
235
+ end
236
+
237
+ it "reconnects the global client" do
238
+ instance_stub Redis::Client, :reconnect do
239
+ force_connection
240
+ rcm_wide.reconnect
241
+ end
242
+ assert_instance_called Redis::Client, :reconnect, 1
243
+ end
244
+
245
+ it "reconnects the redis and global clients" do
246
+ instance_stub Redis::Client, :reconnect do
247
+ force_connection
248
+ rcm_wide.reconnect(:redis)
249
+ end
250
+ assert_instance_called Redis::Client, :reconnect, 2
251
+ end
252
+ end
253
+
254
+ describe "with a narrow connection width" do
255
+ let(:global) { rcm_narrow.connection }
256
+ let(:redis) { rcm_narrow.connection_for(:redis) }
257
+
258
+ def force_connection
259
+ rcm_narrow.connect(:redis)
260
+ global.client.connect
261
+ redis.client.connect
262
+ end
263
+
264
+ it "reconnects the global client" do
265
+ instance_stub Redis::Client, :reconnect do
266
+ force_connection
267
+ rcm_narrow.reconnect
268
+ end
269
+ assert_instance_called Redis::Client, :reconnect, 1
270
+ end
271
+
272
+ it "reconnects the redis and global clients" do
273
+ instance_stub Redis::Client, :reconnect do
274
+ force_connection
275
+ rcm_narrow.reconnect(:redis)
276
+ end
277
+ assert_instance_called Redis::Client, :reconnect, 1
278
+ end
279
+ end
280
+ end
281
+ end
metadata ADDED
@@ -0,0 +1,338 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stockpile-redis
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Austin Ziegler
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: stockpile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis-namespace
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakeredis
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: hoe-doofus
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: hoe-gemspec2
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: hoe-git
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.5'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.5'
139
+ - !ruby/object:Gem::Dependency
140
+ name: hoe-travis
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.2'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.2'
153
+ - !ruby/object:Gem::Dependency
154
+ name: minitest-around
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: minitest-autotest
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: minitest-bisect
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '1.2'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.2'
195
+ - !ruby/object:Gem::Dependency
196
+ name: minitest-focus
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.1'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.1'
209
+ - !ruby/object:Gem::Dependency
210
+ name: minitest-moar
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '0.0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '0.0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: minitest-pretty_diff
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '0.1'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '0.1'
237
+ - !ruby/object:Gem::Dependency
238
+ name: rake
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '10.0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '10.0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: simplecov
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: '0.7'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - "~>"
263
+ - !ruby/object:Gem::Version
264
+ version: '0.7'
265
+ - !ruby/object:Gem::Dependency
266
+ name: hoe
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '3.13'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '3.13'
279
+ description: |-
280
+ stockpile-redis is a connection manager for Redis to be used with
281
+ {Stockpile}[https://github.com/halostatue/stockpile].
282
+ email:
283
+ - halostatue@gmail.com
284
+ executables: []
285
+ extensions: []
286
+ extra_rdoc_files:
287
+ - Contributing.rdoc
288
+ - History.rdoc
289
+ - Licence.rdoc
290
+ - Manifest.txt
291
+ - README.rdoc
292
+ files:
293
+ - ".autotest"
294
+ - ".gemtest"
295
+ - ".minitest.rb"
296
+ - ".travis.yml"
297
+ - ".workenv"
298
+ - Contributing.rdoc
299
+ - Gemfile
300
+ - History.rdoc
301
+ - Licence.rdoc
302
+ - Manifest.txt
303
+ - README.rdoc
304
+ - Rakefile
305
+ - lib/stockpile-redis.rb
306
+ - lib/stockpile/redis.rb
307
+ - test/minitest_config.rb
308
+ - test/test_stockpile_adapter_redis.rb
309
+ - test/test_stockpile_redis.rb
310
+ homepage: https://github.com/halostatue/stockpile-redis/
311
+ licenses:
312
+ - MIT
313
+ metadata: {}
314
+ post_install_message:
315
+ rdoc_options:
316
+ - "--main"
317
+ - README.rdoc
318
+ require_paths:
319
+ - lib
320
+ required_ruby_version: !ruby/object:Gem::Requirement
321
+ requirements:
322
+ - - ">="
323
+ - !ruby/object:Gem::Version
324
+ version: 1.9.2
325
+ required_rubygems_version: !ruby/object:Gem::Requirement
326
+ requirements:
327
+ - - ">="
328
+ - !ruby/object:Gem::Version
329
+ version: '0'
330
+ requirements: []
331
+ rubyforge_project:
332
+ rubygems_version: 2.2.2
333
+ signing_key:
334
+ specification_version: 4
335
+ summary: stockpile-redis is a connection manager for Redis to be used with {Stockpile}[https://github.com/halostatue/stockpile].
336
+ test_files:
337
+ - test/test_stockpile_adapter_redis.rb
338
+ - test/test_stockpile_redis.rb