stockpile 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/History.rdoc +19 -0
- data/Manifest.txt +3 -0
- data/README.rdoc +16 -4
- data/Rakefile +2 -0
- data/lib/stockpile.rb +85 -24
- data/lib/stockpile/base.rb +186 -0
- data/lib/stockpile/memory.rb +170 -0
- data/test/minitest_config.rb +2 -128
- data/test/test_stockpile.rb +85 -9
- data/test/test_stockpile_base.rb +245 -0
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9285056e00c41c3c09036585e9a8b2d5b517b27b
|
4
|
+
data.tar.gz: 84202f9f191b3ee26b30ed7deadef9203b6e5b8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0af27d554f66cd6e22006fdcfa75af45dd83305c5061a7fdf7b222e4836525124a9e6ec941dd9a8d95e743c576bb027f089d52be9b1532e78be2c1def10f47b
|
7
|
+
data.tar.gz: c60a70effa8e3e76b0b764807308db584543dfe61df6d519f4dd7344003db56298bd0c69b52c2ffbdb20aacedbe91ece8f5bf3d11a8980f2d26bc463d4bd01df
|
data/.travis.yml
CHANGED
data/History.rdoc
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
=== 1.1 / 2015-02-10
|
2
|
+
|
3
|
+
* 3 minor enhancements
|
4
|
+
|
5
|
+
* Created a base adapter, Stockpile::Base, that implements the core public
|
6
|
+
interface of a connection manager in a consistent way for argument parsing.
|
7
|
+
|
8
|
+
* Created a memory adapter as an example adapter. (This had previously been
|
9
|
+
a test adapter created in the test environment.)
|
10
|
+
|
11
|
+
* Documented changes to how clients can be specified for Stockpile.new,
|
12
|
+
Stockpile#connect, and Stockpile#connection_for.
|
13
|
+
|
14
|
+
* 1 bugfix
|
15
|
+
|
16
|
+
* Fix {issue #2}[https://github.com/halostatue/stockpile/issues/2], where
|
17
|
+
the use of the cache adapter causes the Stockpile cache manager to
|
18
|
+
initialize too early.
|
19
|
+
|
1
20
|
=== 1.0 / 2015-01-21
|
2
21
|
|
3
22
|
* 1 major enhancement
|
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -14,6 +14,12 @@ implemented connection managers. So far, only Redis has been implemented
|
|
14
14
|
Stockpile also provides an adapter so that its functionality can be accessed
|
15
15
|
from within a module.
|
16
16
|
|
17
|
+
Release 1.1 fixes an issue with early initialization of an injected Stockpile
|
18
|
+
instance during adaptation
|
19
|
+
({stockpile#2}[https://githbub.com/halostatue/stockpile/issues/2]). Several
|
20
|
+
small improvements to Stockpile.new, Stockpile#connect, and
|
21
|
+
Stockpile#connection_for have been documented.
|
22
|
+
|
17
23
|
== Features
|
18
24
|
|
19
25
|
* Stockpile manages key-value store connections. There are two variants:
|
@@ -35,7 +41,7 @@ your Gemfile.
|
|
35
41
|
|
36
42
|
== Synopsis
|
37
43
|
|
38
|
-
wide = Stockpile.new # A Stockpile
|
44
|
+
wide = Stockpile.new # A Stockpile instance.
|
39
45
|
wide.connection.set('hello', 'world') # => 'OK'
|
40
46
|
wide.connection.get('hello') # => 'world'
|
41
47
|
|
@@ -51,6 +57,12 @@ your Gemfile.
|
|
51
57
|
narrow.connection_for(:resque) != narrow.connection # => true
|
52
58
|
narrow.connection_for(:resque).redis == narrow.connection # => true
|
53
59
|
|
60
|
+
# Standard namespace handling.
|
61
|
+
narrow.connection_for(:other, namespace: 'other') !=
|
62
|
+
narrow.connection # => true
|
63
|
+
narrow.connection_for(:other, namespace: 'other').redis !=
|
64
|
+
narrow.connection # => true
|
65
|
+
|
54
66
|
# Show a Stockpile with no adapter capabilities, but name the method
|
55
67
|
# stockpile, not cache. This will still usefully manage connections.
|
56
68
|
module Cacher
|
@@ -132,10 +144,10 @@ be used in Rails. A link to it will be provided here when it is complete.
|
|
132
144
|
== Install
|
133
145
|
|
134
146
|
Stockpile is not intended to be installed by itself, as it does not implement a
|
135
|
-
key-value store specific connection manager. Instead, install
|
136
|
-
|
147
|
+
key-value store specific connection manager. Instead, install a store-specific
|
148
|
+
gem which depends on Stockpile.
|
137
149
|
|
138
|
-
gem 'stockpile-redis', '~> 1.
|
150
|
+
gem 'stockpile-redis', '~> 1.1'
|
139
151
|
|
140
152
|
Or manually install:
|
141
153
|
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
+
require 'rake/clean'
|
5
6
|
|
6
7
|
Hoe.plugin :doofus
|
7
8
|
Hoe.plugin :gemspec2
|
@@ -46,6 +47,7 @@ namespace :test do
|
|
46
47
|
].join('; ')
|
47
48
|
Rake::Task['test'].execute
|
48
49
|
end
|
50
|
+
CLOBBER << 'coverage'
|
49
51
|
end
|
50
52
|
|
51
53
|
# vim: syntax=ruby
|
data/lib/stockpile.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
4
|
|
5
|
-
# Stockpile is a thin wrapper around connections to a fast key-value store
|
6
|
-
# for caching (currently only supporting Redis).
|
5
|
+
# Stockpile is a thin wrapper around connections to a fast key-value store
|
6
|
+
# used for caching (currently only supporting Redis).
|
7
7
|
#
|
8
8
|
# This provides a couple of layers of functionality:
|
9
9
|
#
|
@@ -14,7 +14,7 @@ require 'forwardable'
|
|
14
14
|
class Stockpile
|
15
15
|
extend Forwardable
|
16
16
|
|
17
|
-
VERSION = "1.
|
17
|
+
VERSION = "1.1" # :nodoc:
|
18
18
|
|
19
19
|
@default_manager = nil
|
20
20
|
|
@@ -79,20 +79,34 @@ class Stockpile
|
|
79
79
|
end
|
80
80
|
|
81
81
|
name = options.fetch(:method, :cache).to_sym
|
82
|
-
|
83
|
-
|
82
|
+
mklass = mod.singleton_class
|
84
83
|
default = options.fetch(:default_manager, nil)
|
85
84
|
|
86
|
-
|
85
|
+
mklass.send(:define_method, name) do |init_options = {}|
|
87
86
|
init_options = init_options.merge(default_manager: default)
|
88
87
|
@__stockpile__ ||= ::Stockpile.new(init_options)
|
88
|
+
@__stockpile_triggers__ ||= []
|
89
|
+
|
90
|
+
triggers, @__stockpile_triggers__ = @__stockpile_triggers__, []
|
91
|
+
triggers.each(&:call)
|
92
|
+
|
93
|
+
@__stockpile__
|
89
94
|
end
|
90
95
|
|
91
96
|
if options.fetch(:adaptable, true)
|
92
97
|
adapter = :"#{name}_adapter"
|
93
|
-
|
98
|
+
mklass.send(:define_method, adapter) do |m, k = nil|
|
94
99
|
o = self
|
95
|
-
|
100
|
+
|
101
|
+
@__stockpile_triggers__ ||= []
|
102
|
+
|
103
|
+
trigger = -> { send(name).singleton_class.send(:include, m) }
|
104
|
+
|
105
|
+
if defined?(@__stockpile__) && @__stockpile__
|
106
|
+
trigger.call
|
107
|
+
else
|
108
|
+
@__stockpile_triggers__ << trigger
|
109
|
+
end
|
96
110
|
|
97
111
|
if k
|
98
112
|
mk = k.singleton_class
|
@@ -104,7 +118,7 @@ class Stockpile
|
|
104
118
|
end
|
105
119
|
end
|
106
120
|
|
107
|
-
|
121
|
+
mklass.send(:define_method, :"#{adapter}!") do |m|
|
108
122
|
send(adapter, m, m)
|
109
123
|
end
|
110
124
|
end
|
@@ -131,37 +145,46 @@ class Stockpile
|
|
131
145
|
# through any means.
|
132
146
|
# +clients+:: Connections will be created for the provided list of clients.
|
133
147
|
# These connections must be assigned to their appropriate clients
|
134
|
-
# after initialization. This may also be called +client+.
|
148
|
+
# after initialization. This may also be called +client+. These
|
149
|
+
# values may be provided as names (e.g., +:cache+), or as hashes
|
150
|
+
# of client name to client options (e.g., <tt>{ cache: {
|
151
|
+
# namespace: 'x' } }</tt>). See Stockpile#connect for more
|
152
|
+
# details on this latter format.
|
135
153
|
#
|
136
154
|
# All other options will be passed to the connection provider.
|
137
155
|
#
|
138
156
|
# === Synopsis
|
139
157
|
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
158
|
+
# # Create and assign a connection to Redis.current, Resque, and Rollout.
|
159
|
+
# # Under a narrow connection management width, all three will be the
|
160
|
+
# # same client connection.
|
161
|
+
# options = {
|
162
|
+
# manager: Stockpile::Redis,
|
163
|
+
# clients: [ :redis, :resque ]
|
164
|
+
# }
|
165
|
+
# Stockpile.new(options) do |stockpile|
|
144
166
|
# Redis.current = stockpile.connection_for(:redis)
|
145
167
|
# Resque.redis = stockpile.connection_for(:resque)
|
146
168
|
# # Clients will be created by name if necessary.
|
147
169
|
# $rollout = Rollout.new(stockpile.connection_for(:rollout))
|
148
170
|
# end
|
149
171
|
def initialize(options = {})
|
150
|
-
|
151
|
-
|
152
|
-
|
172
|
+
options = options.dup
|
173
|
+
manager = options.delete(:manager)
|
174
|
+
default = options.delete(:default_manager) || self.class.default_manager
|
153
175
|
|
154
|
-
unless manager
|
176
|
+
unless manager || default
|
155
177
|
raise ArgumentError, "No connection manager provided or set as default."
|
156
178
|
end
|
157
179
|
|
158
|
-
|
180
|
+
manager ||= default
|
181
|
+
|
182
|
+
clients = [
|
183
|
+
Array(options.delete(:clients)), Array(options.delete(:client))
|
184
|
+
].flatten.uniq
|
159
185
|
|
160
|
-
|
161
|
-
k == :manager || k == :clients || k == :client
|
162
|
-
})
|
186
|
+
@manager = manager.new({ narrow: Stockpile.narrow? }.merge(options))
|
163
187
|
|
164
|
-
@manager = manager.new(options)
|
165
188
|
connect(*clients)
|
166
189
|
yield self if block_given?
|
167
190
|
end
|
@@ -183,19 +206,57 @@ class Stockpile
|
|
183
206
|
#
|
184
207
|
# If the connection is using a narrow connection width, the same connection
|
185
208
|
# will be shared.
|
209
|
+
#
|
210
|
+
# === Clients
|
211
|
+
#
|
212
|
+
# +clients+ may be provided in one of several ways:
|
213
|
+
#
|
214
|
+
# * A Hash object, mapping client names to client options.
|
215
|
+
#
|
216
|
+
# connect(redis: nil, rollout: { namespace: 'rollout' })
|
217
|
+
# # Transforms into:
|
218
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
219
|
+
#
|
220
|
+
# * An (implicit) array of client names, for connections with no options
|
221
|
+
# provided.
|
222
|
+
#
|
223
|
+
# connect(:redis, :resque, :rollout)
|
224
|
+
# # Transforms into:
|
225
|
+
# # connect(redis: {}, resque: {}, rollout: {})
|
226
|
+
#
|
227
|
+
# * An array of Hash objects, mapping client names to client options.
|
228
|
+
#
|
229
|
+
# connect({ redis: nil },
|
230
|
+
# { rollout: { namespace: 'rollout' } })
|
231
|
+
# # Transforms into:
|
232
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
233
|
+
#
|
234
|
+
# * A mix of client names and Hash objects:
|
235
|
+
#
|
236
|
+
# connect(:redis, { rollout: { namespace: 'rollout' } })
|
237
|
+
# # Transforms into:
|
238
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
239
|
+
#
|
240
|
+
# ==== Client Options
|
241
|
+
#
|
242
|
+
# Stockpile cache providers will handle the parsing of options to ensure that
|
243
|
+
# only suitable options are passed along (most providers will ignore any
|
244
|
+
# options that change the target system).
|
186
245
|
def_delegator :@manager, :connect
|
187
246
|
|
188
247
|
##
|
189
248
|
# :method: connection_for
|
190
249
|
# :call-seq:
|
191
250
|
# connection_for(client_name)
|
251
|
+
# connection_for(client_name, options)
|
192
252
|
#
|
193
253
|
# Returns a connection for a particular client. If the connection manager is
|
194
254
|
# using a narrow connection width, this returns the same as #connection.
|
195
255
|
#
|
196
256
|
# The +client_name+ of +:all+ will always return +nil+.
|
197
257
|
#
|
198
|
-
# If the requested client does not yet exist, the connection will be created
|
258
|
+
# If the requested client does not yet exist, the connection will be created
|
259
|
+
# with the provided options.
|
199
260
|
def_delegator :@manager, :connection_for
|
200
261
|
|
201
262
|
##
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'stockpile'
|
4
|
+
|
5
|
+
class Stockpile
|
6
|
+
# The base connection manager, providing some common functionality for
|
7
|
+
# connection managers.
|
8
|
+
#
|
9
|
+
# It is not necessary to implement a connection manager from Stockpile::Base,
|
10
|
+
# but it is recommended because it provides all of the core functionality
|
11
|
+
# required of all connection managers, and requires only four integration
|
12
|
+
# points:
|
13
|
+
#
|
14
|
+
# * +initialize+: The constructor for the client connection manager. This
|
15
|
+
# should call +super+ at the beginning of its own implementation, and use
|
16
|
+
# <tt>@options</tt> if further parsing or manipulation of provided options
|
17
|
+
# is required.
|
18
|
+
# * +client_connect+: The actions necessary to connect clients.
|
19
|
+
# * +client_reconnect+: The actions necessary to reconnect clients.
|
20
|
+
# * +client_disconnect+: The actions necessary to disconnect clients.
|
21
|
+
class Base
|
22
|
+
# Create a new connection manager with the provided options.
|
23
|
+
#
|
24
|
+
# == Options
|
25
|
+
#
|
26
|
+
# +narrow+:: Use a narrow connection width if true; if not provided,
|
27
|
+
# uses the value of ::Stockpile.narrow? in this connection
|
28
|
+
# manager.
|
29
|
+
def initialize(options = {})
|
30
|
+
@options = options.dup
|
31
|
+
@narrow = !!@options.fetch(:narrow, ::Stockpile.narrow?)
|
32
|
+
@connection = nil
|
33
|
+
@clients = {}
|
34
|
+
|
35
|
+
@options.delete(:narrow)
|
36
|
+
end
|
37
|
+
|
38
|
+
# The primary connection.
|
39
|
+
attr_reader :connection
|
40
|
+
|
41
|
+
# Indicates if this connection manager is using a narrow connection width.
|
42
|
+
def narrow?
|
43
|
+
@narrow
|
44
|
+
end
|
45
|
+
|
46
|
+
# Connect unless already connected. Additional client connections can be
|
47
|
+
# specified in the parameters as a shorthand for calls to #connection_for.
|
48
|
+
#
|
49
|
+
# If #narrow? is true, the same connection will be used for all clients
|
50
|
+
# managed by this connection manager.
|
51
|
+
#
|
52
|
+
# manager.connect
|
53
|
+
# manager.connection_for(:bar)
|
54
|
+
#
|
55
|
+
# # This means the same as above.
|
56
|
+
# manager.connect(:bar)
|
57
|
+
def connect(*client_names)
|
58
|
+
@connection ||= client_connect
|
59
|
+
|
60
|
+
clients_from(*client_names).each { |client_name, options|
|
61
|
+
connection_for(client_name, options || {})
|
62
|
+
}
|
63
|
+
|
64
|
+
connection
|
65
|
+
end
|
66
|
+
|
67
|
+
# Perform a client connection for a specific +client_name+. A +client_name+
|
68
|
+
# of +:all+ will always return +nil+. If the requested client does not yet
|
69
|
+
# exist, the connection will be created.
|
70
|
+
def connection_for(client_name, options = {})
|
71
|
+
connect unless connection
|
72
|
+
return nil if client_name == :all
|
73
|
+
|
74
|
+
@clients[client_name] ||= client_connect(client_name, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Reconnect some or all clients. The primary connection will always be
|
78
|
+
# reconnected; other clients will be reconnected based on the +clients+
|
79
|
+
# provided. Only clients actively managed by previous calls to #connect
|
80
|
+
# or #connection_for will be reconnected.
|
81
|
+
#
|
82
|
+
# If #reconnect is called with the value +:all+, all currently managed
|
83
|
+
# clients will be reconnected.
|
84
|
+
#
|
85
|
+
# If #narrow? is true, the primary connection will be reconnected, which
|
86
|
+
# reconnects all connections implicitly.
|
87
|
+
def reconnect(*client_names)
|
88
|
+
return unless connection
|
89
|
+
|
90
|
+
client_reconnect
|
91
|
+
|
92
|
+
unless narrow?
|
93
|
+
clients_from(*client_names).each { |client_name, _|
|
94
|
+
client_reconnect(@clients[client_name])
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
connection
|
99
|
+
end
|
100
|
+
|
101
|
+
# Disconnect for some or all clients. The primary connection will always
|
102
|
+
# be disconnected; other clients will be disconnected based on the
|
103
|
+
# +clients+ provided. Only clients actively managed by previous calls to
|
104
|
+
# #connect or #connection_for will be disconnected.
|
105
|
+
#
|
106
|
+
# If #disconnect is called with the value +:all+, all currently managed
|
107
|
+
# clients will be disconnected.
|
108
|
+
#
|
109
|
+
# If #narrow? is true, the primary connection will be disconnected,
|
110
|
+
# which disconnects all connections implicitly.
|
111
|
+
def disconnect(*client_names)
|
112
|
+
return unless connection
|
113
|
+
|
114
|
+
unless narrow?
|
115
|
+
clients_from(*client_names).each { |client_name, _|
|
116
|
+
client_disconnect(@clients[client_name])
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
client_disconnect
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
# Converts +client_names+ into a hash of client names to options.
|
125
|
+
#
|
126
|
+
# * A Hash object, mapping client names to client options.
|
127
|
+
#
|
128
|
+
# connect(redis: nil, rollout: { namespace: 'rollout' })
|
129
|
+
# # Transforms into:
|
130
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
131
|
+
#
|
132
|
+
# * An (implicit) array of client names, for connections with no options
|
133
|
+
# provided.
|
134
|
+
#
|
135
|
+
# connect(:redis, :resque, :rollout)
|
136
|
+
# # Transforms into:
|
137
|
+
# # connect(redis: {}, resque: {}, rollout: {})
|
138
|
+
#
|
139
|
+
# * An array of Hash objects, mapping client names to client options.
|
140
|
+
#
|
141
|
+
# connect({ redis: nil },
|
142
|
+
# { rollout: { namespace: 'rollout' } })
|
143
|
+
# # Transforms into:
|
144
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
145
|
+
#
|
146
|
+
# * A mix of client names and Hash objects:
|
147
|
+
#
|
148
|
+
# connect(:redis, { rollout: { namespace: 'rollout' } })
|
149
|
+
# # Transforms into:
|
150
|
+
# # connect(redis: {}, rollout: { namespace: 'rollout' })
|
151
|
+
def clients_from(*client_names)
|
152
|
+
clients = if client_names.size == 1
|
153
|
+
if client_names.first == :all
|
154
|
+
@clients.keys
|
155
|
+
else
|
156
|
+
client_names
|
157
|
+
end
|
158
|
+
else
|
159
|
+
client_names
|
160
|
+
end
|
161
|
+
clients.map { |v|
|
162
|
+
case v
|
163
|
+
when Hash
|
164
|
+
v
|
165
|
+
else
|
166
|
+
{ v => {} }
|
167
|
+
end
|
168
|
+
}.inject({}, :merge)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Performs a client connect action. Must be implemented by a client.
|
172
|
+
def client_connect(name = nil, options = {})
|
173
|
+
raise NotImplementedError
|
174
|
+
end
|
175
|
+
|
176
|
+
# Performs a client reconnect action. Must be implemented by a client.
|
177
|
+
def client_reconnect(client = connect())
|
178
|
+
raise NotImplementedError
|
179
|
+
end
|
180
|
+
|
181
|
+
# Performs a client disconnect action. Must be implemented by a client.
|
182
|
+
def client_disconnect(client = connect())
|
183
|
+
raise NotImplementedError
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'stockpile/base'
|
4
|
+
|
5
|
+
class Stockpile
|
6
|
+
# An in-memory connection manager, providing a complete example of how a
|
7
|
+
# Stockpile connection manager could be made.
|
8
|
+
class Memory < Stockpile::Base
|
9
|
+
class Data # :nodoc:
|
10
|
+
class << self
|
11
|
+
attr_reader :data
|
12
|
+
|
13
|
+
def reset
|
14
|
+
@data = {}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
reset
|
19
|
+
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
@connected = false
|
24
|
+
@options = options
|
25
|
+
connect
|
26
|
+
end
|
27
|
+
|
28
|
+
def connect
|
29
|
+
@connected = true
|
30
|
+
end
|
31
|
+
alias_method :reconnect, :connect
|
32
|
+
|
33
|
+
def disconnect
|
34
|
+
@connected = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def connected?
|
38
|
+
!!@connected
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(key)
|
42
|
+
check_valid!
|
43
|
+
self.class.data[key]
|
44
|
+
end
|
45
|
+
|
46
|
+
def set(key, value)
|
47
|
+
check_valid!
|
48
|
+
self.class.data[key] = value
|
49
|
+
end
|
50
|
+
|
51
|
+
def hget(key, field)
|
52
|
+
raise unless connected?
|
53
|
+
valid_hkey!(key)[field]
|
54
|
+
end
|
55
|
+
|
56
|
+
def hset(key, field, value)
|
57
|
+
raise unless connected?
|
58
|
+
valid_hkey!(key)[field] = value
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def check_valid!
|
63
|
+
raise unless connected?
|
64
|
+
end
|
65
|
+
|
66
|
+
def valid_hkey!(key)
|
67
|
+
check_valid!
|
68
|
+
case h = self.class.data[key]
|
69
|
+
when nil
|
70
|
+
h = (self.class.data[key] = {})
|
71
|
+
when Hash
|
72
|
+
nil
|
73
|
+
else
|
74
|
+
raise
|
75
|
+
end
|
76
|
+
h
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# :singleton-method: new
|
82
|
+
# :call-seq:
|
83
|
+
# new(options = {})
|
84
|
+
#
|
85
|
+
# Create a new Memory connection manager.
|
86
|
+
|
87
|
+
##
|
88
|
+
# :attr_reader: connection
|
89
|
+
#
|
90
|
+
# The primary connection.
|
91
|
+
|
92
|
+
##
|
93
|
+
# :method: narrow?
|
94
|
+
#
|
95
|
+
# Indicates if this connection manager is using a narrow connection width.
|
96
|
+
|
97
|
+
##
|
98
|
+
# :method: connect
|
99
|
+
# :call-seq:
|
100
|
+
# connect(*client_names)
|
101
|
+
#
|
102
|
+
# Connect unless already connected. Additional client connections can be
|
103
|
+
# specified in the parameters as a shorthand for calls to #connection_for.
|
104
|
+
#
|
105
|
+
# If #narrow? is true, the same connection will be used for all clients
|
106
|
+
# managed by this connection manager.
|
107
|
+
#
|
108
|
+
# manager.connect
|
109
|
+
# manager.connection_for(:bar)
|
110
|
+
#
|
111
|
+
# # This means the same as above.
|
112
|
+
# manager.connect(:bar)
|
113
|
+
|
114
|
+
##
|
115
|
+
# :method: connection_for
|
116
|
+
# :call-seq:
|
117
|
+
# connection_for(client_name, options = {})
|
118
|
+
#
|
119
|
+
# Perform a client connection for a specific +client_name+. A +client_name+
|
120
|
+
# of +:all+ will always return +nil+. If the requested client does not yet
|
121
|
+
# exist, the connection will be created.
|
122
|
+
|
123
|
+
##
|
124
|
+
# :method: reconnect
|
125
|
+
# :call-seq:
|
126
|
+
# reconnect(*client_names)
|
127
|
+
#
|
128
|
+
# Reconnect some or all clients. The primary connection will always be
|
129
|
+
# reconnected; other clients will be reconnected based on the +clients+
|
130
|
+
# provided. Only clients actively managed by previous calls to #connect or
|
131
|
+
# #connection_for will be reconnected.
|
132
|
+
#
|
133
|
+
# If #reconnect is called with the value +:all+, all currently managed
|
134
|
+
# clients will be reconnected.
|
135
|
+
#
|
136
|
+
# If #narrow? is true, the primary connection will be reconnected, which
|
137
|
+
# reconnects all connections implicitly.
|
138
|
+
|
139
|
+
##
|
140
|
+
# :method: disconnect
|
141
|
+
# :call-seq:
|
142
|
+
# disconnect(*client_names)
|
143
|
+
#
|
144
|
+
# Disconnect for some or all clients. The primary connection will always
|
145
|
+
# be disconnected; other clients will be disconnected based on the
|
146
|
+
# +clients+ provided. Only clients actively managed by previous calls to
|
147
|
+
# #connect or #connection_for will be disconnected.
|
148
|
+
#
|
149
|
+
# If #disconnect is called with the value +:all+, all currently managed
|
150
|
+
# clients will be disconnected.
|
151
|
+
#
|
152
|
+
# If #narrow? is true, the primary connection will be disconnected,
|
153
|
+
# which disconnects all connections implicitly.
|
154
|
+
|
155
|
+
##
|
156
|
+
private
|
157
|
+
def client_connect(name = nil, options = {})
|
158
|
+
return connection if connection && narrow?
|
159
|
+
Data.new(@options.merge(options))
|
160
|
+
end
|
161
|
+
|
162
|
+
def client_reconnect(client = connection())
|
163
|
+
client.reconnect if client
|
164
|
+
end
|
165
|
+
|
166
|
+
def client_disconnect(client = connection())
|
167
|
+
client.disconnect if client
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/test/minitest_config.rb
CHANGED
@@ -7,138 +7,12 @@ require 'minitest/focus'
|
|
7
7
|
require 'minitest/moar'
|
8
8
|
require 'minitest/bisect'
|
9
9
|
|
10
|
-
require 'stockpile'
|
11
|
-
|
12
|
-
class StockpileTestManager
|
13
|
-
class Connection
|
14
|
-
class << self
|
15
|
-
attr_reader :data
|
16
|
-
|
17
|
-
def reset_data
|
18
|
-
@data = Hash.new { |h, k| h[k] = {} }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
reset_data
|
23
|
-
|
24
|
-
def initialize
|
25
|
-
@connected = false
|
26
|
-
connect
|
27
|
-
end
|
28
|
-
|
29
|
-
def connect
|
30
|
-
@connected = true
|
31
|
-
end
|
32
|
-
alias_method :reconnect, :connect
|
33
|
-
|
34
|
-
def disconnect
|
35
|
-
@connected = false
|
36
|
-
end
|
37
|
-
|
38
|
-
def connected?
|
39
|
-
!!@connected
|
40
|
-
end
|
41
|
-
|
42
|
-
def get(key)
|
43
|
-
raise unless connected?
|
44
|
-
self.class.data[key]
|
45
|
-
end
|
46
|
-
|
47
|
-
def set(key, value)
|
48
|
-
raise unless connected?
|
49
|
-
self.class.data[key] = value
|
50
|
-
end
|
51
|
-
|
52
|
-
def hget(key, field)
|
53
|
-
raise unless connected?
|
54
|
-
self.class.data[key][field]
|
55
|
-
end
|
56
|
-
|
57
|
-
def hset(key, field, value)
|
58
|
-
raise unless connected?
|
59
|
-
self.class.data[key][field] = value
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def initialize(options = {})
|
64
|
-
@narrow = !!options.fetch(:narrow, ::Stockpile.narrow?)
|
65
|
-
@connection = nil
|
66
|
-
@clients = {}
|
67
|
-
end
|
68
|
-
|
69
|
-
attr_reader :connection
|
70
|
-
|
71
|
-
def narrow?
|
72
|
-
@narrow
|
73
|
-
end
|
74
|
-
|
75
|
-
def connect(*client_names)
|
76
|
-
@connection ||= connect_for_any
|
77
|
-
|
78
|
-
clients_from(*client_names).each { |client_name|
|
79
|
-
connection_for(client_name)
|
80
|
-
}
|
81
|
-
|
82
|
-
connection
|
83
|
-
end
|
84
|
-
|
85
|
-
def connection_for(client_name)
|
86
|
-
connect unless connection
|
87
|
-
return nil if client_name == :all
|
88
|
-
@clients[client_name] ||= connect_for_any
|
89
|
-
end
|
90
|
-
|
91
|
-
def reconnect(*client_names)
|
92
|
-
return unless connection
|
93
|
-
|
94
|
-
connection.reconnect
|
95
|
-
|
96
|
-
unless narrow?
|
97
|
-
clients_from(*client_names).each { |client_name|
|
98
|
-
client = @clients[client_name]
|
99
|
-
client.reconnect if client
|
100
|
-
}
|
101
|
-
end
|
102
|
-
|
103
|
-
connection
|
104
|
-
end
|
105
|
-
|
106
|
-
def disconnect(*client_names)
|
107
|
-
return unless connection
|
108
|
-
|
109
|
-
unless narrow?
|
110
|
-
clients_from(*client_names).each { |client_name|
|
111
|
-
client = @clients[client_name]
|
112
|
-
client.disconnect if client
|
113
|
-
}
|
114
|
-
end
|
115
|
-
|
116
|
-
connection.disconnect
|
117
|
-
end
|
118
|
-
|
119
|
-
private
|
120
|
-
def clients_from(*client_names)
|
121
|
-
if client_names.size == 1
|
122
|
-
if client_names.first == :all
|
123
|
-
@clients.keys
|
124
|
-
else
|
125
|
-
client_names
|
126
|
-
end
|
127
|
-
else
|
128
|
-
client_names
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def connect_for_any
|
133
|
-
return connection if connection && narrow?
|
134
|
-
Connection.new
|
135
|
-
end
|
136
|
-
end
|
10
|
+
require 'stockpile/memory'
|
137
11
|
|
138
12
|
module Minitest::ENVStub
|
139
13
|
def setup
|
140
14
|
super
|
141
|
-
|
15
|
+
Stockpile::Memory::Data.reset
|
142
16
|
end
|
143
17
|
|
144
18
|
def stub_env env, options = {}, *block_args, &block
|
data/test/test_stockpile.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'minitest_config'
|
2
|
-
require 'stockpile'
|
3
2
|
require 'time'
|
4
3
|
|
5
4
|
describe Stockpile do
|
@@ -18,6 +17,7 @@ describe Stockpile do
|
|
18
17
|
end
|
19
18
|
|
20
19
|
describe ".inject!" do
|
20
|
+
let(:cls) { Class.new }
|
21
21
|
let(:mod) { Module.new }
|
22
22
|
let(:lrt) {
|
23
23
|
Module.new do
|
@@ -29,10 +29,24 @@ describe Stockpile do
|
|
29
29
|
Time.parse(value) if value
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
def job_ran(job, value = nil)
|
34
|
+
if value
|
35
|
+
connection.set(job, !!value)
|
36
|
+
else
|
37
|
+
!!connection.get(job)
|
38
|
+
end
|
39
|
+
end
|
32
40
|
end
|
33
41
|
}
|
34
42
|
|
35
|
-
|
43
|
+
it "throws an ArgumentError unless it's a class or module" do
|
44
|
+
assert_raises ArgumentError do
|
45
|
+
::Stockpile.inject!(Object.new)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "Stockpile.inject!(Module):" do
|
36
50
|
before { ::Stockpile.inject!(mod) }
|
37
51
|
|
38
52
|
it "defines Mod.cache" do
|
@@ -84,7 +98,9 @@ describe Stockpile do
|
|
84
98
|
end
|
85
99
|
|
86
100
|
describe "Stockpile.inject!(Mod, method: :stockpile, adaptable: false)" do
|
87
|
-
before
|
101
|
+
before do
|
102
|
+
::Stockpile.inject!(mod, method: :stockpile, adaptable: false)
|
103
|
+
end
|
88
104
|
|
89
105
|
it "defines Mod.stockpile" do
|
90
106
|
assert_respond_to mod, :stockpile
|
@@ -100,8 +116,29 @@ describe Stockpile do
|
|
100
116
|
let(:now) { Time.now }
|
101
117
|
let(:iso) { now.utc.iso8601 }
|
102
118
|
before do
|
103
|
-
::Stockpile.inject!(mod,
|
104
|
-
|
119
|
+
::Stockpile.inject!(mod, default_manager: Stockpile::Memory)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "queues adaptation until Stockpile has been initialized" do
|
123
|
+
stub Stockpile, :new do
|
124
|
+
mod.cache_adapter(lrt)
|
125
|
+
refute_called Stockpile, :new
|
126
|
+
refute_nil mod.instance_variable_get(:@__stockpile_triggers__)
|
127
|
+
refute_empty mod.instance_variable_get(:@__stockpile_triggers__)
|
128
|
+
end
|
129
|
+
|
130
|
+
assert_equal({ namespace: 'n' },
|
131
|
+
mod.cache(namespace: 'n').connection.options)
|
132
|
+
assert_respond_to mod.cache, :last_run_time
|
133
|
+
assert_respond_to mod.cache, :job_ran
|
134
|
+
end
|
135
|
+
|
136
|
+
it "adapts an initialized Stockpile immediately" do
|
137
|
+
mod.cache
|
138
|
+
mod.cache_adapter(lrt)
|
139
|
+
assert_respond_to mod.cache, :last_run_time
|
140
|
+
assert_respond_to mod.cache, :job_ran
|
141
|
+
assert_empty mod.instance_variable_get(:@__stockpile_triggers__)
|
105
142
|
end
|
106
143
|
|
107
144
|
it "adapts the cache with last_run_time" do
|
@@ -124,10 +161,49 @@ describe Stockpile do
|
|
124
161
|
assert_equal iso, lrt.last_run_time('foo', now)
|
125
162
|
assert_equal now.to_i, lrt.last_run_time('foo').to_i
|
126
163
|
end
|
164
|
+
|
165
|
+
it "adapts the cache with job_ran" do
|
166
|
+
mod.cache_adapter(lrt)
|
167
|
+
refute mod.cache.job_ran('foo')
|
168
|
+
assert mod.cache.job_ran('foo', true)
|
169
|
+
assert mod.cache.job_ran('foo')
|
170
|
+
end
|
171
|
+
|
172
|
+
it "adapts the module with last_run_time" do
|
173
|
+
mod.cache_adapter(lrt, mod)
|
174
|
+
refute mod.job_ran('foo')
|
175
|
+
assert mod.job_ran('foo', true)
|
176
|
+
assert mod.job_ran('foo')
|
177
|
+
end
|
178
|
+
|
179
|
+
it "adapts the lrt module with last_run_time" do
|
180
|
+
mod.cache_adapter!(lrt)
|
181
|
+
refute lrt.job_ran('foo')
|
182
|
+
assert lrt.job_ran('foo', true)
|
183
|
+
assert lrt.job_ran('foo')
|
184
|
+
end
|
127
185
|
end
|
128
|
-
end
|
129
186
|
|
130
|
-
|
131
|
-
|
132
|
-
|
187
|
+
describe "Stockpile.inject!(Class):" do
|
188
|
+
before { ::Stockpile.inject!(cls) }
|
189
|
+
|
190
|
+
it "defines cls.cache" do
|
191
|
+
assert_respond_to cls, :cache
|
192
|
+
end
|
193
|
+
|
194
|
+
it "defines cls.cache_adapter" do
|
195
|
+
assert_respond_to cls, :cache_adapter
|
196
|
+
end
|
197
|
+
|
198
|
+
it "defines cls.cache_adapter!" do
|
199
|
+
assert_respond_to cls, :cache_adapter!
|
200
|
+
end
|
201
|
+
|
202
|
+
it "Fails cache initialization" do
|
203
|
+
assert_raises ArgumentError do
|
204
|
+
cls.cache
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
133
209
|
end
|
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'minitest_config'
|
2
|
+
|
3
|
+
describe Stockpile::Base do
|
4
|
+
def assert_clients expected_clients, connector
|
5
|
+
actual_clients = connector.instance_variable_get(:@clients).keys
|
6
|
+
assert_equal actual_clients.sort, expected_clients.sort
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:mem) {
|
10
|
+
stub_env({}) { Stockpile::Memory.new }
|
11
|
+
}
|
12
|
+
let(:mem_namespace) {
|
13
|
+
stub_env({}) { Stockpile::Memory.new(namespace: 'Z') }
|
14
|
+
}
|
15
|
+
let(:mem_wide) {
|
16
|
+
stub_env({}) { Stockpile::Memory.new(narrow: false) }
|
17
|
+
}
|
18
|
+
let(:mem_narrow) {
|
19
|
+
stub_env({}) { Stockpile::Memory.new(narrow: true) }
|
20
|
+
}
|
21
|
+
|
22
|
+
describe 'constructor' do
|
23
|
+
it "uses the default connection width by default" do
|
24
|
+
stub ::Stockpile, :narrow?, lambda { false } do
|
25
|
+
refute Stockpile::Base.new.narrow?,
|
26
|
+
"should be narrow, but is not"
|
27
|
+
end
|
28
|
+
|
29
|
+
stub ::Stockpile, :narrow?, lambda { true } do
|
30
|
+
assert Stockpile::Base.new.narrow?,
|
31
|
+
"is not narrow, but should be"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can be told which connection width to use explicitly" do
|
36
|
+
stub ::Stockpile, :narrow?, lambda { false } do
|
37
|
+
assert mem_narrow.narrow?
|
38
|
+
end
|
39
|
+
|
40
|
+
stub ::Stockpile, :narrow?, lambda { true } do
|
41
|
+
refute mem_wide.narrow?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "passes settings through to the client" do
|
46
|
+
options = {
|
47
|
+
url: 'test://xyz/'
|
48
|
+
}
|
49
|
+
mem = ::Stockpile::Memory.new(options)
|
50
|
+
assert_equal 'test://xyz/', mem.connect.options[:url]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "has no clients by default" do
|
54
|
+
assert_clients [], ::Stockpile::Memory.new
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#connect" do
|
59
|
+
it "raises NotImplementedError unless #client_connect is implemented" do
|
60
|
+
assert_raises NotImplementedError do
|
61
|
+
::Stockpile::Base.new.connect
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "creates a connection to the client" do
|
66
|
+
assert_nil mem.connection
|
67
|
+
refute_nil mem.connect
|
68
|
+
end
|
69
|
+
|
70
|
+
it "creates a namespaced connection to the client" do
|
71
|
+
assert_nil mem_namespace.connection
|
72
|
+
refute_nil mem_namespace.connect
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "with a wide connection width" do
|
76
|
+
before do
|
77
|
+
mem_wide.connect(:hoge, { quux: {} })
|
78
|
+
end
|
79
|
+
|
80
|
+
it "connects multiple clients" do
|
81
|
+
assert_clients [ :hoge, :quux ], mem_wide
|
82
|
+
end
|
83
|
+
|
84
|
+
it "connects *different* clients" do
|
85
|
+
refute_same mem_wide.connection, mem_wide.connection_for(:hoge)
|
86
|
+
refute_same mem_wide.connection, mem_wide.connection_for(:quux)
|
87
|
+
refute_same mem_wide.connection_for(:hoge), mem_wide.connection_for(:quux)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "with a narrow connection width" do
|
92
|
+
before do
|
93
|
+
mem_narrow.connect(:hoge, :quux)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "appears to connect multiple clients" do
|
97
|
+
assert_clients [ :hoge, :quux ], mem_narrow
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns identical clients" do
|
101
|
+
assert_same mem_narrow.connection, mem_narrow.connection_for(:hoge)
|
102
|
+
assert_same mem_narrow.connection, mem_narrow.connection_for(:quux)
|
103
|
+
assert_same mem_narrow.connection_for(:hoge), mem_narrow.connection_for(:quux)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#connection_for" do
|
109
|
+
it "raises NotImplementedError unless #client_connect is implemented" do
|
110
|
+
assert_raises NotImplementedError do
|
111
|
+
instance_stub ::Stockpile::Base, :connection, -> { true } do
|
112
|
+
::Stockpile::Base.new.connection_for(:foo)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "with a wide connection width" do
|
118
|
+
it "connects the main client" do
|
119
|
+
mem_wide.connection_for(:global)
|
120
|
+
assert mem_wide.connection
|
121
|
+
refute_same mem_wide.connection, mem_wide.connection_for(:global)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "with a narrow connection width" do
|
126
|
+
it "connects the main client" do
|
127
|
+
mem_narrow.connection_for(:global)
|
128
|
+
assert mem_narrow.connection
|
129
|
+
assert_same mem_narrow.connection, mem_narrow.connection_for(:global)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
let(:connection) { Stockpile::Memory::Data }
|
135
|
+
|
136
|
+
describe "#disconnect" do
|
137
|
+
it "raises NotImplementedError unless #client_disconnect is implemented" do
|
138
|
+
base = ::Stockpile::Base.new
|
139
|
+
assert_raises NotImplementedError do
|
140
|
+
instance_stub ::Stockpile::Base, :connect do
|
141
|
+
instance_stub ::Stockpile::Base, :connection, -> { true } do
|
142
|
+
base.disconnect
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "with a wide connection width" do
|
149
|
+
let(:global) { mem_wide.connection }
|
150
|
+
let(:hoge) { mem_wide.connection_for(:hoge) }
|
151
|
+
|
152
|
+
before do
|
153
|
+
mem_wide.connect(:hoge)
|
154
|
+
assert hoge.connected? && global.connected?
|
155
|
+
end
|
156
|
+
|
157
|
+
it "disconnects the global client" do
|
158
|
+
mem_wide.disconnect
|
159
|
+
assert hoge.connected? && !global.connected?
|
160
|
+
end
|
161
|
+
|
162
|
+
it "disconnects the redis and global clients" do
|
163
|
+
mem_wide.disconnect(:hoge)
|
164
|
+
refute hoge.connected? || global.connected?
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "with a narrow connection width" do
|
169
|
+
let(:global) { mem_narrow.connection }
|
170
|
+
let(:hoge) { mem_narrow.connection_for(:hoge) }
|
171
|
+
|
172
|
+
before do
|
173
|
+
mem_narrow.connect(:hoge)
|
174
|
+
assert hoge.connected? && global.connected?
|
175
|
+
end
|
176
|
+
|
177
|
+
it "#disconnect disconnects all clients" do
|
178
|
+
mem_narrow.disconnect
|
179
|
+
refute hoge.connected? || global.connected?
|
180
|
+
end
|
181
|
+
|
182
|
+
it "#disconnect(:hoge) disconnects all clients" do
|
183
|
+
mem_narrow.disconnect(:hoge)
|
184
|
+
refute hoge.connected? || global.connected?
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#reconnect" do
|
190
|
+
it "raises NotImplementedError unless #client_reconnect is implemented" do
|
191
|
+
base = ::Stockpile::Base.new
|
192
|
+
assert_raises NotImplementedError do
|
193
|
+
instance_stub ::Stockpile::Base, :connect do
|
194
|
+
instance_stub ::Stockpile::Base, :connection, -> { true } do
|
195
|
+
base.reconnect
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe "with a wide connection width" do
|
202
|
+
let(:global) { mem_wide.connection }
|
203
|
+
let(:hoge) { mem_wide.connection_for(:hoge) }
|
204
|
+
|
205
|
+
before do
|
206
|
+
mem_wide.connect(:hoge)
|
207
|
+
assert hoge.connected? && global.connected?
|
208
|
+
mem_wide.disconnect(:all)
|
209
|
+
refute hoge.connected? || global.connected?
|
210
|
+
end
|
211
|
+
|
212
|
+
it "reconnects the global client" do
|
213
|
+
mem_wide.reconnect
|
214
|
+
assert !hoge.connected? && global.connected?
|
215
|
+
end
|
216
|
+
|
217
|
+
it "reconnects the redis and global clients" do
|
218
|
+
mem_wide.reconnect(:hoge)
|
219
|
+
assert hoge.connected? && global.connected?
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "with a narrow connection width" do
|
224
|
+
let(:global) { mem_narrow.connection }
|
225
|
+
let(:hoge) { mem_narrow.connection_for(:hoge) }
|
226
|
+
|
227
|
+
def force_connection
|
228
|
+
mem_narrow.connect(:hoge)
|
229
|
+
assert hoge.connected? && global.connected?
|
230
|
+
mem_wide.disconnect(:all)
|
231
|
+
refute hoge.connected? || global.connected?
|
232
|
+
end
|
233
|
+
|
234
|
+
it "#reconnect reconnects the all clients" do
|
235
|
+
mem_narrow.reconnect
|
236
|
+
assert hoge.connected? && global.connected?
|
237
|
+
end
|
238
|
+
|
239
|
+
it "#reconnect(:hoge:) reconnects all clients" do
|
240
|
+
mem_narrow.reconnect(:hoge)
|
241
|
+
assert hoge.connected? && global.connected?
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stockpile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Austin Ziegler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -228,6 +228,12 @@ description: |-
|
|
228
228
|
|
229
229
|
Stockpile also provides an adapter so that its functionality can be accessed
|
230
230
|
from within a module.
|
231
|
+
|
232
|
+
Release 1.1 fixes an issue with early initialization of an injected Stockpile
|
233
|
+
instance during adaptation
|
234
|
+
({stockpile#2}[https://githbub.com/halostatue/stockpile/issues/2]). Several
|
235
|
+
small improvements to Stockpile.new, Stockpile#connect, and
|
236
|
+
Stockpile#connection_for have been documented.
|
231
237
|
email:
|
232
238
|
- halostatue@gmail.com
|
233
239
|
executables: []
|
@@ -251,8 +257,11 @@ files:
|
|
251
257
|
- README.rdoc
|
252
258
|
- Rakefile
|
253
259
|
- lib/stockpile.rb
|
260
|
+
- lib/stockpile/base.rb
|
261
|
+
- lib/stockpile/memory.rb
|
254
262
|
- test/minitest_config.rb
|
255
263
|
- test/test_stockpile.rb
|
264
|
+
- test/test_stockpile_base.rb
|
256
265
|
homepage: https://github.com/halostatue/stockpile/
|
257
266
|
licenses:
|
258
267
|
- MIT
|
@@ -279,5 +288,4 @@ rubygems_version: 2.2.2
|
|
279
288
|
signing_key:
|
280
289
|
specification_version: 4
|
281
290
|
summary: Stockpile is a simple key-value store connection manager framework
|
282
|
-
test_files:
|
283
|
-
- test/test_stockpile.rb
|
291
|
+
test_files: []
|