retriable 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ .rvmrc
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ v1.2.0. Fork the retryable-rb repo. Extend the Kernel module with the retriable method so you can use it anywhere without having to include it in every class. Update gemspec, Gemfile, and Raketask. Remove echoe dependency.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in retriable.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011 Robert Sosinski (http://www.robertsosinski.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ Introduction
2
+ ============
3
+
4
+ Retriable is an easy to use DSL to retry code if an exception is raised. This is especially useful when interacting with unreliable services that fail randomly.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ gem install retriable
10
+
11
+ # In your ruby application
12
+ require 'retriable'
13
+
14
+ # In your Gemfile
15
+ gem 'retriable'
16
+
17
+ Using Retriable
18
+ ---------------
19
+
20
+ Code wrapped in a retriable block will be retried if a failure occurs. As such, code attempted once, will be retried again for another attempt if it fails to run.
21
+
22
+ require 'retriable'
23
+
24
+ class Api
25
+ # Use it in methods that interact with unreliable services
26
+ def get
27
+ retriable do
28
+ # code here...
29
+ end
30
+ end
31
+ end
32
+
33
+ By default, Retriable will rescue any exception inherited from `Exception`, retry once (for a total of two attempts) and sleep for a random amount time (between 0 to 100 milliseconds, in 10 millisecond increments). You can choose additional options by passing them via an options `Hash`.
34
+
35
+ retriable :on => Timeout::Error, :times => 3, :sleep => 1 do
36
+ # code here...
37
+ end
38
+
39
+ This example will only retry on a `Timeout::Error`, retry 3 times (for a total of 4 attempts) and sleep for a full second before each retry. You can also specify multiple errors to retry on by passing an array.
40
+
41
+ retriable :on => [Timeout::Error, Errno::ECONNRESET] do
42
+ # code here...
43
+ end
44
+
45
+ You can also have Ruby retry immediately after a failure by passing `false` as the sleep option.
46
+
47
+ retriable :sleep => false do
48
+ # code here...
49
+ end
50
+
51
+ Retriable also allows for callbacks to be defined, which is useful to log failures for analytics purposes or cleanup after repeated failures. Retriable has three types of callbacks: `then`, `finally`, and `always`.
52
+
53
+ `then`: Run every time a failure occurs.
54
+
55
+ `finally`: Run when the number of retries runs out.
56
+
57
+ `always`: Run when the code wrapped in a retriable block passes or when the number of retries runs out.
58
+
59
+ The `then` and `finally` callbacks pass the exception raised, which can be used for logging or error control. All three callbacks also have a `handler`, which provides an interface to pass data between the code wrapped in the retriable block and the callbacks defined.
60
+
61
+ Furthermore, each callback provides the number of `attempts`, `retries` and `times` that the wrapped code should be retried. As these are specified in a `Proc`, unnecessary variables can be left out of the parameter list.
62
+
63
+ then_cb = Proc.new do |exception, handler, attempts, retries, times|
64
+ log "#{exception.class}: '#{exception.message}' - #{attempts} attempts, #{retries} out of #{times} retries left."}
65
+ end
66
+
67
+ finally_cb = Proc.new do |exception, handler|
68
+ log "#{exception.class} raised too many times. First attempt at #{handler[:start]} and final attempt at #{Time.now}"
69
+ end
70
+
71
+ always_cb = Proc.new do |handler, attempts|
72
+ log "total time for #{attempts} attempts: #{Time.now - handler[:start]}"
73
+ end
74
+
75
+ retriable :then => then_cb do, :finally => finally_cb, :always => always_cb |handler|
76
+ handler[:start] ||= Time.now
77
+
78
+ # code here...
79
+ end
80
+
81
+ Credits
82
+ -------
83
+
84
+ Retriable was originally forked from the retryable-rb gem by [Robert Sosinski](https://github.com/robertsosinski), which in turn originally inspired by code written by [Michael Celona](http://github.com/mcelona) and later assisted by [David Malin](http://github.com/dmalin).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+
8
+ task :default => :test
9
+
10
+ desc "Run tests"
11
+ task :test do
12
+ Rake::TestTask.new do |t|
13
+ t.libs << 'lib' << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+ end
data/lib/retriable.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'retriable/version'
2
+
3
+ module Kernel
4
+ def retriable(options = {})
5
+ opts = {:on => Exception, :times => 1}.merge(options)
6
+ handler = {}
7
+
8
+ retry_exception = opts[:on].is_a?(Array) ? opts[:on] : [opts[:on]]
9
+ times = retries = opts[:times]
10
+ attempts = 0
11
+
12
+ begin
13
+ attempts += 1
14
+
15
+ return yield(handler)
16
+ rescue *retry_exception => exception
17
+ opts[:then].call(exception, handler, attempts, retries, times) if opts[:then]
18
+
19
+ if attempts <= times
20
+ sleep(opts[:sleep] || (rand(11) / 100.0)) unless opts[:sleep] == false
21
+ retries -= 1
22
+ retry
23
+ else
24
+ opts[:finally].call(exception, handler, attempts, retries, times) if opts[:finally]
25
+ raise exception
26
+ end
27
+ ensure
28
+ opts[:always].call(handler, attempts, retries, times) if opts[:always]
29
+ end
30
+
31
+ yield(handler)
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Retriable
4
+ VERSION = '1.2.0'
5
+ end
data/retriable.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "retriable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "retriable"
7
+ s.version = Retriable::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jack Chu"]
10
+ s.email = ["jack@jackchu.com"]
11
+ s.homepage = %q{http://github.com/kamui/retriable}
12
+ s.summary = %q{Easy to use DSL to retry code if an exception is raised.}
13
+ s.description = %q{Easy to use DSL to retry code if an exception is raised.}
14
+
15
+ s.rubyforge_project = "retriable"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,72 @@
1
+ $:.unshift(File.dirname(__FILE__) + "../lib")
2
+
3
+ require 'test/unit'
4
+ require 'retriable'
5
+
6
+ class RetriableTest < Test::Unit::TestCase
7
+ def test_without_arguments
8
+ i = 0
9
+
10
+ retriable do
11
+ i += 1
12
+
13
+ raise Exception.new
14
+ end
15
+ rescue Exception
16
+ assert_equal i, 2
17
+ end
18
+
19
+ def test_with_one_exception_and_two_times
20
+ i = 0
21
+
22
+ retriable :on => EOFError, :times => 2 do
23
+ i += 1
24
+
25
+ raise EOFError.new
26
+ end
27
+
28
+ rescue EOFError
29
+ assert_equal i, 3
30
+ end
31
+
32
+ def test_with_arguments_and_handler
33
+ i = 0
34
+
35
+ then_cb = Proc.new do |e, h, a, r, t|
36
+ assert_equal e.class, ArgumentError
37
+ assert h[:value]
38
+
39
+ assert_equal a, i
40
+ assert_equal r, 6 - a
41
+ assert_equal t, 5
42
+ end
43
+
44
+ finally_cb = Proc.new do |e, h, a, r, t|
45
+ assert_equal e.class, ArgumentError
46
+ assert h[:value]
47
+
48
+ assert_equal a, 6
49
+ assert_equal r, 0
50
+ assert_equal t, 5
51
+ end
52
+
53
+ always_cb = Proc.new do |h, a, r, t|
54
+ assert h[:value]
55
+
56
+ assert_equal a, 6
57
+ assert_equal r, 0
58
+ assert_equal t, 5
59
+ end
60
+
61
+ retriable :on => [EOFError, ArgumentError], :then => then_cb, :finally => finally_cb, :always => always_cb, :times => 5, :sleep => 0.2 do |h|
62
+ i += 1
63
+
64
+ h[:value] = true
65
+
66
+ raise ArgumentError.new
67
+ end
68
+
69
+ rescue ArgumentError
70
+ assert_equal i, 6
71
+ end
72
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: retriable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jack Chu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-10 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Easy to use DSL to retry code if an exception is raised.
15
+ email:
16
+ - jack@jackchu.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - CHANGELOG
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - lib/retriable.rb
28
+ - lib/retriable/version.rb
29
+ - retriable.gemspec
30
+ - test/retriable_test.rb
31
+ homepage: http://github.com/kamui/retriable
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project: retriable
51
+ rubygems_version: 1.8.15
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Easy to use DSL to retry code if an exception is raised.
55
+ test_files:
56
+ - test/retriable_test.rb