attempt 0.6.1 → 0.6.3
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +6 -0
- data/Gemfile +2 -8
- data/README.md +30 -32
- data/Rakefile +1 -1
- data/attempt.gemspec +12 -5
- data/lib/attempt.rb +40 -33
- data/spec/attempt_spec.rb +24 -22
- data.tar.gz.sig +0 -0
- metadata +37 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc6bbb832eed33acf584990eca716d23081ee12b3a507e6e47d0b8298adae3fa
|
4
|
+
data.tar.gz: 590719816eb1bea8e4e59607f997936eec9303efb5a7507ee11558023f3e2fb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fe34c159cc36940f05dc8c2108a0b1be600d8c57eacfa4f9d258f2d735fbf21e0524863f3d45568c7074d9ef9825bfe972d1bea102330e0846910dd415478b0
|
7
|
+
data.tar.gz: 61b00a2d427952342b5cf76b2a000691c30a4f341b27a8c150059b4a465701df29904bfd2c5759de97f236156116353f0a97de4695f05ee6f6d6ceee2e8ec98c
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.6.3 - 26-Jun-2024
|
2
|
+
* Rubocop cleanup.
|
3
|
+
|
4
|
+
## 0.6.2 - 2-Jun-2022
|
5
|
+
* The safe_timeout library is not used on MS Windows.
|
6
|
+
|
1
7
|
## 0.6.1 - 20-Oct-2020
|
2
8
|
* Switched the README, MANIFEST and CHANGES to markdown format.
|
3
9
|
* Fiddling with the .travis.yml file again.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
-
|
1
|
+
[](https://github.com/djberg96/attempt/actions/workflows/ruby.yml)
|
2
2
|
|
3
|
+
## Description
|
3
4
|
A thin wrapper for begin + rescue + sleep + retry.
|
4
5
|
|
5
6
|
## Installation
|
7
|
+
`gem install attempt`
|
6
8
|
|
7
|
-
|
9
|
+
## Adding the trusted cert
|
10
|
+
`gem cert --add <(curl -Ls https://raw.githubusercontent.com/djberg96/attempt/main/certs/djberg96_pub.pem)`
|
8
11
|
|
9
12
|
## Synopsis
|
13
|
+
```ruby
|
14
|
+
require 'attempt'
|
15
|
+
|
16
|
+
# Attempt to ftp to some host, trying 3 times with 30 seconds between
|
17
|
+
# attempts before finally raising an error.
|
10
18
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# Attempt to ftp to some host, trying 3 times with 30 seconds between
|
15
|
-
# attempts before finally raising an error.
|
19
|
+
attempt(tries: 3, interval: 30){
|
20
|
+
Net::FTP.open(host, user, passwd){ ... }
|
21
|
+
}
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
code.attempt{
|
28
|
-
Net::FTP.open(host, user, passwd){ ... }
|
29
|
-
}
|
23
|
+
# Or, do things the long way...
|
24
|
+
code = Attempt.new do |a|
|
25
|
+
a.tries = 3
|
26
|
+
a.interval = 30
|
27
|
+
end
|
28
|
+
|
29
|
+
code.attempt{
|
30
|
+
Net::FTP.open(host, user, passwd){ ... }
|
31
|
+
}
|
30
32
|
```
|
31
33
|
|
32
34
|
## Known Bugs
|
33
|
-
|
34
35
|
None that I'm aware of. If you find any bugs, please log them on the project page at:
|
35
36
|
|
36
37
|
https://github.com/djberg96/attempt
|
37
38
|
|
38
39
|
## Caveats
|
39
|
-
|
40
40
|
Use with caution. Specifically, make sure you aren't inadvertantly
|
41
41
|
wrapping code that already performs sleep + retry. Otherwise, you'll
|
42
42
|
end up with a series of nested retry's that could take much longer to
|
@@ -49,36 +49,34 @@ As of version 0.3.0, this library requires structured_warnings 0.3.0 or
|
|
49
49
|
later. This is necessary because of changes in Ruby 2.4.
|
50
50
|
|
51
51
|
Update: I've switched from the timeout library in the standard library to
|
52
|
-
the safe_timeout library which should improve things.
|
53
|
-
structured_warnings library requirement is now 0.4.0 or later
|
54
|
-
work with Ruby 2.7.
|
52
|
+
the safe_timeout library on non-Windows platforms which should improve things.
|
53
|
+
In addition, the structured_warnings library requirement is now 0.4.0 or later
|
54
|
+
in order to work with Ruby 2.7.
|
55
55
|
|
56
56
|
## Future Plans
|
57
|
-
|
58
57
|
Add the ability to set an absolute maximum number of seconds to prevent
|
59
58
|
nested sleep/retry from delaying attempts longer than expected.
|
60
59
|
|
61
60
|
Replace the timeout library with a self selecting pipe if possible.
|
62
61
|
|
63
62
|
## Acknowledgements
|
64
|
-
|
65
63
|
This library is partially based on Mark Fowler's 'Attempt' Perl module.
|
66
64
|
|
67
|
-
##
|
65
|
+
## See Also
|
66
|
+
If you're looking for a heavier but more robust solution designed for remote
|
67
|
+
services, please take a look at gems like "circuitbox" or "faulty".
|
68
68
|
|
69
|
+
## Warranty
|
69
70
|
This package is provided "as is" and without any express or
|
70
71
|
implied warranties, including, without limitation, the implied
|
71
72
|
warranties of merchantability and fitness for a particular purpose.
|
72
73
|
|
73
74
|
## License
|
74
|
-
|
75
75
|
Apache-2.0
|
76
76
|
|
77
77
|
## Copyright
|
78
|
-
|
79
|
-
(C) 2006-2020, Daniel J. Berger
|
78
|
+
(C) 2006-2022, Daniel J. Berger
|
80
79
|
All Rights Reserved
|
81
80
|
|
82
81
|
## Author
|
83
|
-
|
84
82
|
Daniel J. Berger
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ namespace :gem do
|
|
8
8
|
desc 'Build the attempt gem'
|
9
9
|
task :create => [:clean] do
|
10
10
|
require 'rubygems/package'
|
11
|
-
spec =
|
11
|
+
spec = Gem::Specification.load('attempt.gemspec')
|
12
12
|
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
|
13
13
|
Gem::Package.build(spec)
|
14
14
|
end
|
data/attempt.gemspec
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'attempt'
|
5
|
-
spec.version = '0.6.
|
5
|
+
spec.version = '0.6.3'
|
6
6
|
spec.author = 'Daniel J. Berger'
|
7
7
|
spec.license = 'Apache-2.0'
|
8
8
|
spec.email = 'djberg96@gmail.com'
|
@@ -13,12 +13,19 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.cert_chain = Dir['certs/*']
|
14
14
|
|
15
15
|
spec.metadata = {
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'
|
19
|
-
'
|
16
|
+
'homepage_uri' => 'https://github.com/djberg96/attempt',
|
17
|
+
'documentation_uri' => 'https://github.com/djberg96/attempt/wiki',
|
18
|
+
'changelog_uri' => 'https://github.com/djberg96/attempt/blob/main/CHANGES.md',
|
19
|
+
'source_code_uri' => 'https://github.com/djberg96/attempt/blob/main/lib/attempt.rb',
|
20
|
+
'bug_tracker_uri' => 'https://github.com/djberg96/attempt/issues',
|
21
|
+
'wiki_uri' => 'https://github.com/djberg96/attempt/wiki',
|
22
|
+
'rubygems_mfa_required' => 'true',
|
23
|
+
'github_repo' => 'https://github.com/djberg96/attempt'
|
20
24
|
}
|
21
25
|
|
26
|
+
spec.add_development_dependency('rake')
|
27
|
+
spec.add_development_dependency('rubocop')
|
28
|
+
|
22
29
|
spec.add_dependency('structured_warnings', '~> 0.4.0')
|
23
30
|
spec.add_dependency('safe_timeout', '~> 0.0.5')
|
24
31
|
spec.add_dependency('rspec', '~> 3.9')
|
data/lib/attempt.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if File::ALT_SEPARATOR
|
4
|
+
require 'timeout'
|
5
|
+
else
|
6
|
+
require 'safe_timeout'
|
7
|
+
end
|
8
|
+
|
2
9
|
require 'structured_warnings'
|
3
10
|
|
4
11
|
# The Attempt class encapsulates methods related to multiple attempts at
|
5
12
|
# running the same method before actually failing.
|
6
13
|
class Attempt
|
7
|
-
|
8
14
|
# The version of the attempt library.
|
9
|
-
VERSION = '0.6.
|
15
|
+
VERSION = '0.6.3'
|
10
16
|
|
11
17
|
# Warning raised if an attempt fails before the maximum number of tries
|
12
18
|
# has been reached.
|
@@ -51,7 +57,7 @@ class Attempt
|
|
51
57
|
# * warnings - Boolean value that indicates whether or not errors are treated as warnings
|
52
58
|
# until the maximum number of attempts has been made. The default is true.
|
53
59
|
# * timeout - Boolean value to indicate whether or not to automatically wrap your
|
54
|
-
# proc in a SafeTimeout block. The default is false.
|
60
|
+
# proc in a Timeout/SafeTimeout block. The default is false.
|
55
61
|
#
|
56
62
|
# Example:
|
57
63
|
#
|
@@ -74,18 +80,18 @@ class Attempt
|
|
74
80
|
# You will not typically use this method directly, but the Kernel#attempt
|
75
81
|
# method instead.
|
76
82
|
#
|
77
|
-
def attempt
|
83
|
+
def attempt(&block)
|
78
84
|
count = 1
|
79
85
|
begin
|
80
86
|
if @timeout
|
81
|
-
|
87
|
+
File::ALT_SEPARATOR ? Timeout.timeout(@timeout, &block) : SafeTimeout.timeout(@timeout, &block)
|
82
88
|
else
|
83
89
|
yield
|
84
90
|
end
|
85
|
-
rescue @level =>
|
91
|
+
rescue @level => err
|
86
92
|
@tries -= 1
|
87
93
|
if @tries > 0
|
88
|
-
msg = "Error on attempt # #{count}: #{
|
94
|
+
msg = "Error on attempt # #{count}: #{err}; retrying"
|
89
95
|
count += 1
|
90
96
|
warn Warning, msg if @warnings
|
91
97
|
|
@@ -102,30 +108,31 @@ class Attempt
|
|
102
108
|
end
|
103
109
|
end
|
104
110
|
|
111
|
+
# Extend the Kernel module with a simple interface for the Attempt class.
|
105
112
|
module Kernel
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
113
|
+
# :call-seq:
|
114
|
+
# attempt(tries: 3, interval: 60, timeout: 10){ # some op }
|
115
|
+
#
|
116
|
+
# Attempt to perform the operation in the provided block up to +tries+
|
117
|
+
# times, sleeping +interval+ between each try. By default the number
|
118
|
+
# of tries defaults to 3, the interval defaults to 60 seconds, and there
|
119
|
+
# is no timeout specified.
|
120
|
+
#
|
121
|
+
# If +timeout+ is provided then the operation is wrapped in a Timeout
|
122
|
+
# block as well. This is handy for those rare occasions when an IO
|
123
|
+
# connection could hang indefinitely, for example.
|
124
|
+
#
|
125
|
+
# If the operation still fails the (last) error is then re-raised.
|
126
|
+
#
|
127
|
+
# This is really just a convenient wrapper for Attempt.new + Attempt#attempt.
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
#
|
131
|
+
# # Make 3 attempts to connect to the database, 60 seconds apart.
|
132
|
+
# attempt{ DBI.connect(dsn, user, passwd) }
|
133
|
+
#
|
134
|
+
def attempt(**kwargs, &block)
|
135
|
+
object = Attempt.new(**kwargs)
|
136
|
+
object.attempt(&block)
|
137
|
+
end
|
131
138
|
end
|
data/spec/attempt_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#####################################################################
|
2
4
|
# attempt_spec.rb
|
3
5
|
#
|
@@ -19,49 +21,49 @@ RSpec.describe Attempt do
|
|
19
21
|
@tries = 2
|
20
22
|
@interval = 0.1
|
21
23
|
@timeout = 0.1
|
22
|
-
|
24
|
+
@value = 0
|
25
|
+
end
|
26
|
+
|
27
|
+
after do
|
28
|
+
@value = 0
|
29
|
+
end
|
30
|
+
|
31
|
+
after(:all) do
|
32
|
+
$stderr = STDERR
|
23
33
|
end
|
24
34
|
|
25
|
-
example
|
26
|
-
expect(Attempt::VERSION).to eq('0.6.
|
35
|
+
example 'version constant is set to expected value' do
|
36
|
+
expect(Attempt::VERSION).to eq('0.6.3')
|
27
37
|
expect(Attempt::VERSION).to be_frozen
|
28
38
|
end
|
29
39
|
|
30
|
-
example
|
40
|
+
example 'attempt works as expected without arguments' do
|
31
41
|
expect{ attempt{ 2 + 2 } }.not_to raise_error
|
32
42
|
end
|
33
43
|
|
34
|
-
example
|
35
|
-
expect{ attempt(tries: @tries){
|
36
|
-
expect(
|
44
|
+
example 'attempt retries the number of times specified' do
|
45
|
+
expect{ attempt(tries: @tries){ @value += 1; raise if @value < 2 } }.not_to raise_error
|
46
|
+
expect(@value).to eq(2)
|
37
47
|
end
|
38
48
|
|
39
|
-
example
|
49
|
+
example 'attempt retries the number of times specified with interval' do
|
40
50
|
expect{
|
41
|
-
attempt(tries: @tries, interval: @interval){
|
51
|
+
attempt(tries: @tries, interval: @interval){ @value += 1; raise if @value < 2 }
|
42
52
|
}.not_to raise_error
|
43
|
-
expect(
|
53
|
+
expect(@value).to eq(2)
|
44
54
|
end
|
45
55
|
|
46
|
-
example
|
56
|
+
example 'attempt retries the number of times specified with interval and timeout' do
|
47
57
|
expect{
|
48
|
-
attempt(tries: @tries, interval: @interval, timeout: @timeout){
|
58
|
+
attempt(tries: @tries, interval: @interval, timeout: @timeout){ @value += 1; raise if @value < 2 }
|
49
59
|
}.not_to raise_error
|
50
60
|
end
|
51
61
|
|
52
|
-
example
|
62
|
+
example 'attempt raises a timeout error if timeout value is exceeded' do
|
53
63
|
expect{ attempt(tries: 1, interval: 1, timeout: @timeout){ sleep 5 } }.to raise_error(Timeout::Error)
|
54
64
|
end
|
55
65
|
|
56
|
-
example
|
66
|
+
example 'attempt raises exception as expected' do
|
57
67
|
expect{ attempt(tries: 2, interval: 2){ raise } }.to raise_error(RuntimeError)
|
58
68
|
end
|
59
|
-
|
60
|
-
after do
|
61
|
-
$after = 0
|
62
|
-
end
|
63
|
-
|
64
|
-
after(:all) do
|
65
|
-
$stderr = STDERR
|
66
|
-
end
|
67
69
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attempt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -35,8 +35,36 @@ cert_chain:
|
|
35
35
|
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
|
36
36
|
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date:
|
38
|
+
date: 2024-06-26 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: rake
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rubocop
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
40
68
|
- !ruby/object:Gem::Dependency
|
41
69
|
name: structured_warnings
|
42
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,10 +132,14 @@ homepage: https://github.com/djberg96/attempt
|
|
104
132
|
licenses:
|
105
133
|
- Apache-2.0
|
106
134
|
metadata:
|
107
|
-
|
108
|
-
|
135
|
+
homepage_uri: https://github.com/djberg96/attempt
|
136
|
+
documentation_uri: https://github.com/djberg96/attempt/wiki
|
137
|
+
changelog_uri: https://github.com/djberg96/attempt/blob/main/CHANGES.md
|
138
|
+
source_code_uri: https://github.com/djberg96/attempt/blob/main/lib/attempt.rb
|
109
139
|
bug_tracker_uri: https://github.com/djberg96/attempt/issues
|
110
140
|
wiki_uri: https://github.com/djberg96/attempt/wiki
|
141
|
+
rubygems_mfa_required: 'true'
|
142
|
+
github_repo: https://github.com/djberg96/attempt
|
111
143
|
post_install_message:
|
112
144
|
rdoc_options: []
|
113
145
|
require_paths:
|
@@ -123,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
155
|
- !ruby/object:Gem::Version
|
124
156
|
version: '0'
|
125
157
|
requirements: []
|
126
|
-
rubygems_version: 3.
|
158
|
+
rubygems_version: 3.4.10
|
127
159
|
signing_key:
|
128
160
|
specification_version: 4
|
129
161
|
summary: A thin wrapper for begin + rescue + sleep + retry
|
metadata.gz.sig
CHANGED
Binary file
|