retriable 3.0.2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfe5a1956e7b8921928094fd4306632da5852693
4
- data.tar.gz: bc171d15fa1f55ce45151f6e6ce6976b2082a415
3
+ metadata.gz: 9be10833c09da3a93748eaaae5d13577ee8c520a
4
+ data.tar.gz: a370e7ea1a328865b3235f316e07bacdc19b6bb1
5
5
  SHA512:
6
- metadata.gz: 80395340aa4890214aeb12f331904da265f42af80d4e8bd7400e532d7a47f4828abc659f7ae629a74f6d16ce77f1e88b23fc8518ca4531087d23a566ec5bcacc
7
- data.tar.gz: c8385720ed1095508eae24dc918eb620ea4715b13d38ef7d2c921abd65f9fb05f6e95065307be644819405a1d9411e20961e95e06b734aae1333b54c3f45745d
6
+ metadata.gz: bd0ff1af0d8f50320fa8ff29ed4e53b56fbb33d62638a00206d2e9a816ae11082638b10ae6642f7bf98895f3f48b87e886bbe3dc1997b19863825f0c330ed759
7
+ data.tar.gz: aec007409a818cb5758c3e853cb6bd684d4676deee14c089f4b10f7fd3284554f71dd5d8079345622b1b99e4f23bf3a874f1c2371916e5e9b8fce13d35009318
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .DS_Store
@@ -6,7 +6,7 @@ Style/Documentation:
6
6
 
7
7
  Style/TrailingCommaInArguments:
8
8
  EnforcedStyleForMultiline: comma
9
-
9
+
10
10
  Style/TrailingCommaInLiteral:
11
11
  EnforcedStyleForMultiline: comma
12
12
 
@@ -19,6 +19,9 @@ Style/IndentArray:
19
19
  Style/IndentHash:
20
20
  Enabled: false
21
21
 
22
+ Style/NegatedIf:
23
+ Enabled: false
24
+
22
25
  Metrics/ClassLength:
23
26
  Enabled: false
24
27
 
@@ -10,7 +10,7 @@ rvm:
10
10
  - 2.4.1
11
11
  - rbx
12
12
  - jruby-9.0.5.0
13
- - jruby-9.1.8.0
13
+ - jruby-9.1.12.0
14
14
  - ruby-head
15
15
  - jruby-head
16
16
 
@@ -1,5 +1,9 @@
1
1
  ## HEAD
2
2
 
3
+ ## 3.1.0
4
+
5
+ * Added contexts feature. Thanks to @apurvis.
6
+
3
7
  ## 3.0.2
4
8
 
5
9
  * Add configuration and options validation.
data/README.md CHANGED
@@ -223,6 +223,49 @@ ensure
223
223
  end
224
224
  ```
225
225
 
226
+ ## Contexts
227
+
228
+ Contexts allow you to coordinate sets of Retriable options across an application. Each context is basically an argument hash for `Retriable.retriable` that is stored in the `Retriable.config` as a simple `Hash` and is accessible by name. For example:
229
+
230
+ ```ruby
231
+ Retriable.configure do |c|
232
+ c.contexts[:aws] = {
233
+ tries: 3,
234
+ base_interval: 5,
235
+ on_retry: Proc.new { puts 'Curse you, AWS!' }
236
+ }
237
+ c.contexts[:mysql] = {
238
+ tries: 10,
239
+ multiplier: 2.5,
240
+ on: Mysql::DeadlockException
241
+ }
242
+ end
243
+ ```
244
+
245
+ This will create two contexts, `aws` and `mysql`, which allow you to reuse different backoff strategies across your application without continually passing those strategy options to the `retriable` method.
246
+
247
+ These are used simply by calling `Retriable.with_context`:
248
+
249
+ ```ruby
250
+ # Will retry all exceptions
251
+ Retriable.with_context(:aws) do
252
+ # aws_call
253
+ end
254
+
255
+ # Will retry Mysql::DeadlockException
256
+ Retriable.with_context(:mysql) do
257
+ # write_to_table
258
+ end
259
+ ```
260
+
261
+ You can even temporarily override individual options for a configured context:
262
+
263
+ ```ruby
264
+ Retriable.with_context(:mysql, tries: 30) do
265
+ # write_to_table
266
+ end
267
+ ```
268
+
226
269
  ## Kernel Extension
227
270
 
228
271
  If you want to call `Retriable.retriable` without the `Retriable` module prefix and you don't mind extending `Kernel`,
@@ -246,6 +289,10 @@ and then you can call `#retriable` in any context like this:
246
289
  retriable do
247
290
  # code here...
248
291
  end
292
+
293
+ retriable_with_context(:api) do
294
+ # code here...
295
+ end
249
296
  ```
250
297
 
251
298
  ## Proxy Wrapper Object
@@ -6,7 +6,7 @@ require_relative "retriable/version"
6
6
  module Retriable
7
7
  module_function
8
8
 
9
- def self.configure
9
+ def configure
10
10
  yield(config)
11
11
  end
12
12
 
@@ -14,6 +14,14 @@ module Retriable
14
14
  @config ||= Config.new
15
15
  end
16
16
 
17
+ def with_context(context_key, options = {}, &block)
18
+ if !config.contexts.key?(context_key)
19
+ raise ArgumentError, "#{context_key} not found in Retriable.config.contexts. Here the available contexts: #{config.contexts.keys}"
20
+ end
21
+
22
+ retriable(config.contexts[context_key].merge(options), &block) if block
23
+ end
24
+
17
25
  def retriable(opts = {})
18
26
  local_config = opts.empty? ? config : Config.new(config.to_h.merge(opts))
19
27
 
@@ -40,7 +48,7 @@ module Retriable
40
48
  base_interval: base_interval,
41
49
  multiplier: multiplier,
42
50
  max_interval: max_interval,
43
- rand_factor: rand_factor,
51
+ rand_factor: rand_factor
44
52
  ).intervals
45
53
  end
46
54
 
@@ -9,6 +9,7 @@ module Retriable
9
9
  :timeout,
10
10
  :on,
11
11
  :on_retry,
12
+ :contexts,
12
13
  ].freeze
13
14
 
14
15
  attr_accessor(*ATTRIBUTES)
@@ -27,6 +28,7 @@ module Retriable
27
28
  @timeout = nil
28
29
  @on = [StandardError]
29
30
  @on_retry = nil
31
+ @contexts = {}
30
32
 
31
33
  opts.each do |k, v|
32
34
  raise ArgumentError, "#{k} is not a valid option" if !ATTRIBUTES.include?(k)
@@ -4,4 +4,8 @@ module Kernel
4
4
  def retriable(opts = {}, &block)
5
5
  Retriable.retriable(opts, &block)
6
6
  end
7
+
8
+ def retriable_with_context(context_key, opts = {}, &block)
9
+ Retriable.with_context(context_key, opts, &block)
10
+ end
7
11
  end
@@ -1,3 +1,3 @@
1
1
  module Retriable
2
- VERSION = "3.0.2".freeze
2
+ VERSION = "3.1.0".freeze
3
3
  end
@@ -45,6 +45,10 @@ describe Retriable::Config do
45
45
  expect(subject.new.on_retry).must_be_nil
46
46
  end
47
47
 
48
+ it "contexts defaults to {}" do
49
+ expect(subject.new.contexts).must_equal Hash.new
50
+ end
51
+
48
52
  it "raises errors on invalid configuration" do
49
53
  assert_raises ArgumentError do
50
54
  subject.new(does_not_exist: 123)
@@ -376,4 +376,59 @@ describe Retriable do
376
376
  Retriable.retriable(does_not_exist: 123)
377
377
  end
378
378
  end
379
+
380
+ describe "#with_context" do
381
+ before do
382
+ Retriable.configure do |c|
383
+ c.sleep_disabled = true
384
+ c.contexts[:sql] = { tries: 1 }
385
+ c.contexts[:api] = { tries: 3 }
386
+ end
387
+ end
388
+
389
+ it "sql context stops at first try if the block does not raise an exception" do
390
+ tries = 0
391
+ subject.with_context(:sql) do
392
+ tries += 1
393
+ end
394
+
395
+ expect(tries).must_equal 1
396
+ end
397
+
398
+ it "with_context respects the context options" do
399
+ tries = 0
400
+
401
+ expect do
402
+ subject.with_context(:api) do
403
+ tries += 1
404
+ raise StandardError.new, "StandardError occurred"
405
+ end
406
+ end.must_raise StandardError
407
+
408
+ expect(tries).must_equal 3
409
+ end
410
+
411
+ it "with_context allows override options" do
412
+ tries = 0
413
+
414
+ expect do
415
+ subject.with_context(:sql, tries: 5) do
416
+ tries += 1
417
+ raise StandardError.new, "StandardError occurred"
418
+ end
419
+ end.must_raise StandardError
420
+
421
+ expect(tries).must_equal 5
422
+ end
423
+
424
+ it "raises an ArgumentError when the context isn't found" do
425
+ tries = 0
426
+
427
+ expect do
428
+ subject.with_context(:wtf) do
429
+ tries += 1
430
+ end
431
+ end.must_raise ArgumentError
432
+ end
433
+ end
379
434
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retriable
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Chu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-27 00:00:00.000000000 Z
11
+ date: 2017-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler