retriable 3.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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