@@ -9,7 +9,7 @@ module Storage
9
9
# cascading failures in your application when evaluating circuits. Always
10
10
# wrap this backend with a {FaultTolerantProxy} to limit the effect of
11
11
# these types of events.
12
- class Redis # rubocop:disable Metrics/ClassLength
12
+ class Redis
13
13
# Separates the time/status for history entry strings
14
14
ENTRY_SEPARATOR = ':'
15
15
@@ -95,7 +95,7 @@ def initialize(**options, &block)
95
95
# @param (see Interface#get_options)
96
96
# @return (see Interface#get_options)
97
97
def get_options ( circuit )
98
- json = redis { |r | r . get ( options_key ( circuit ) ) }
98
+ json = redis { |r | r . get ( options_key ( circuit . name ) ) }
99
99
return if json . nil?
100
100
101
101
JSON . parse ( json , symbolize_names : true )
@@ -110,7 +110,7 @@ def get_options(circuit)
110
110
# @return (see Interface#set_options)
111
111
def set_options ( circuit , stored_options )
112
112
redis do |r |
113
- r . set ( options_key ( circuit ) , JSON . dump ( stored_options ) , ex : options . circuit_ttl )
113
+ r . set ( options_key ( circuit . name ) , JSON . dump ( stored_options ) , ex : options . circuit_ttl )
114
114
end
115
115
end
116
116
@@ -120,7 +120,7 @@ def set_options(circuit, stored_options)
120
120
# @param (see Interface#entry)
121
121
# @return (see Interface#entry)
122
122
def entry ( circuit , time , success , status )
123
- key = entries_key ( circuit )
123
+ key = entries_key ( circuit . name )
124
124
result = pipe do |r |
125
125
r . sadd ( list_key , circuit . name )
126
126
r . expire ( list_key , options . circuit_ttl + options . list_granularity ) if options . circuit_ttl
@@ -139,11 +139,11 @@ def entry(circuit, time, success, status)
139
139
# @param (see Interface#open)
140
140
# @return (see Interface#open)
141
141
def open ( circuit , opened_at )
142
- key = state_key ( circuit )
142
+ key = state_key ( circuit . name )
143
143
ex = options . circuit_ttl
144
144
result = watch_exec ( key , [ 'closed' , nil ] ) do |m |
145
145
m . set ( key , 'open' , ex : ex )
146
- m . set ( opened_at_key ( circuit ) , opened_at , ex : ex )
146
+ m . set ( opened_at_key ( circuit . name ) , opened_at , ex : ex )
147
147
end
148
148
149
149
result && result [ 0 ] == 'OK'
@@ -155,7 +155,7 @@ def open(circuit, opened_at)
155
155
# @param (see Interface#reopen)
156
156
# @return (see Interface#reopen)
157
157
def reopen ( circuit , opened_at , previous_opened_at )
158
- key = opened_at_key ( circuit )
158
+ key = opened_at_key ( circuit . name )
159
159
result = watch_exec ( key , [ previous_opened_at . to_s ] ) do |m |
160
160
m . set ( key , opened_at , ex : options . circuit_ttl )
161
161
end
@@ -169,11 +169,11 @@ def reopen(circuit, opened_at, previous_opened_at)
169
169
# @param (see Interface#close)
170
170
# @return (see Interface#close)
171
171
def close ( circuit )
172
- key = state_key ( circuit )
172
+ key = state_key ( circuit . name )
173
173
ex = options . circuit_ttl
174
174
result = watch_exec ( key , [ 'open' ] ) do |m |
175
175
m . set ( key , 'closed' , ex : ex )
176
- m . del ( entries_key ( circuit ) )
176
+ m . del ( entries_key ( circuit . name ) )
177
177
end
178
178
179
179
result && result [ 0 ] == 'OK'
@@ -187,7 +187,7 @@ def close(circuit)
187
187
# @param (see Interface#lock)
188
188
# @return (see Interface#lock)
189
189
def lock ( circuit , state )
190
- redis { |r | r . set ( lock_key ( circuit ) , state ) }
190
+ redis { |r | r . set ( lock_key ( circuit . name ) , state ) }
191
191
end
192
192
193
193
# Unlock a circuit
@@ -196,7 +196,7 @@ def lock(circuit, state)
196
196
# @param (see Interface#unlock)
197
197
# @return (see Interface#unlock)
198
198
def unlock ( circuit )
199
- redis { |r | r . del ( lock_key ( circuit ) ) }
199
+ redis { |r | r . del ( lock_key ( circuit . name ) ) }
200
200
end
201
201
202
202
# Reset a circuit
@@ -205,14 +205,15 @@ def unlock(circuit)
205
205
# @param (see Interface#reset)
206
206
# @return (see Interface#reset)
207
207
def reset ( circuit )
208
+ name = circuit . is_a? ( Circuit ) ? circuit . name : circuit
208
209
pipe do |r |
209
210
r . del (
210
- entries_key ( circuit ) ,
211
- opened_at_key ( circuit ) ,
212
- lock_key ( circuit ) ,
213
- options_key ( circuit )
211
+ entries_key ( name ) ,
212
+ opened_at_key ( name ) ,
213
+ lock_key ( name ) ,
214
+ options_key ( name )
214
215
)
215
- r . set ( state_key ( circuit ) , 'closed' , ex : options . circuit_ttl )
216
+ r . set ( state_key ( name ) , 'closed' , ex : options . circuit_ttl )
216
217
end
217
218
end
218
219
@@ -224,10 +225,10 @@ def reset(circuit)
224
225
def status ( circuit )
225
226
futures = { }
226
227
pipe do |r |
227
- futures [ :state ] = r . get ( state_key ( circuit ) )
228
- futures [ :lock ] = r . get ( lock_key ( circuit ) )
229
- futures [ :opened_at ] = r . get ( opened_at_key ( circuit ) )
230
- futures [ :entries ] = r . lrange ( entries_key ( circuit ) , 0 , -1 )
228
+ futures [ :state ] = r . get ( state_key ( circuit . name ) )
229
+ futures [ :lock ] = r . get ( lock_key ( circuit . name ) )
230
+ futures [ :opened_at ] = r . get ( opened_at_key ( circuit . name ) )
231
+ futures [ :entries ] = r . lrange ( entries_key ( circuit . name ) , 0 , -1 )
231
232
end
232
233
233
234
state = futures [ :state ] . value &.to_sym || :closed
@@ -249,7 +250,7 @@ def status(circuit)
249
250
# @param (see Interface#history)
250
251
# @return (see Interface#history)
251
252
def history ( circuit )
252
- entries = redis { |r | r . lrange ( entries_key ( circuit ) , 0 , -1 ) }
253
+ entries = redis { |r | r . lrange ( entries_key ( circuit . name ) , 0 , -1 ) }
253
254
map_entries ( entries ) . reverse
254
255
end
255
256
@@ -260,6 +261,21 @@ def list
260
261
redis { |r | r . sunion ( *all_list_keys ) }
261
262
end
262
263
264
+ # Reset all circuits
265
+ #
266
+ # This does not empty the list of circuits as returned by {#list}. This is
267
+ # because that would be a thread-usafe operation that could result in
268
+ # circuits not being in the list.
269
+ #
270
+ # This implmenentation resets circuits individually, and will be very
271
+ # slow for large numbers of circuits. It should not be used in production
272
+ # code.
273
+ #
274
+ # @return [void]
275
+ def clear
276
+ list . each { |c | reset ( c ) }
277
+ end
278
+
263
279
# Redis storage is not fault-tolerant
264
280
#
265
281
# @return [true]
@@ -276,33 +292,33 @@ def key(*parts)
276
292
[ options . key_prefix , *parts ] . join ( options . key_separator )
277
293
end
278
294
279
- def ckey ( circuit , *parts )
280
- key ( 'circuit' , circuit . name , *parts )
295
+ def ckey ( circuit_name , *parts )
296
+ key ( 'circuit' , circuit_name , *parts )
281
297
end
282
298
283
299
# @return [String] The key for circuit options
284
- def options_key ( circuit )
285
- ckey ( circuit , 'options' )
300
+ def options_key ( circuit_name )
301
+ ckey ( circuit_name , 'options' )
286
302
end
287
303
288
304
# @return [String] The key for circuit state
289
- def state_key ( circuit )
290
- ckey ( circuit , 'state' )
305
+ def state_key ( circuit_name )
306
+ ckey ( circuit_name , 'state' )
291
307
end
292
308
293
309
# @return [String] The key for circuit run history entries
294
- def entries_key ( circuit )
295
- ckey ( circuit , 'entries' )
310
+ def entries_key ( circuit_name )
311
+ ckey ( circuit_name , 'entries' )
296
312
end
297
313
298
314
# @return [String] The key for circuit locks
299
- def lock_key ( circuit )
300
- ckey ( circuit , 'lock' )
315
+ def lock_key ( circuit_name )
316
+ ckey ( circuit_name , 'lock' )
301
317
end
302
318
303
319
# @return [String] The key for circuit opened_at
304
- def opened_at_key ( circuit )
305
- ckey ( circuit , 'opened_at' )
320
+ def opened_at_key ( circuit_name )
321
+ ckey ( circuit_name , 'opened_at' )
306
322
end
307
323
308
324
# Get the current key to add circuit names to
0 commit comments