wait 0.4.1 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,9 @@
1
1
  class Wait
2
2
  class BaseCounter
3
- attr_reader :attempt
3
+ attr_accessor :logger
4
+ attr_reader :attempt
4
5
 
5
- def initialize(logger, total)
6
- @logger = logger
6
+ def initialize(total)
7
7
  # Attempt to prevent causing an infinite loop by being very strict about
8
8
  # the value passed.
9
9
  unless total.is_a?(Fixnum) and total > 0
@@ -11,7 +11,6 @@ class Wait
11
11
  end
12
12
 
13
13
  @total = total
14
- reset
15
14
  end
16
15
 
17
16
  # Called before all attempts to reset the counter.
@@ -32,7 +31,9 @@ class Wait
32
31
 
33
32
  # Logs the current attempt count.
34
33
  def log
35
- @logger.debug "[Counter] attempt #{self}"
34
+ return if @logger.nil?
35
+
36
+ @logger.debug("Counter") { "attempt #{self}" }
36
37
  end
37
38
 
38
39
  # Returns a string representation of the current count.
@@ -1,19 +1,22 @@
1
1
  class Wait
2
2
  class BaseDelayer
3
- def initialize(logger, initial_delay)
4
- @logger = logger
5
- @delay = initial_delay
3
+ attr_accessor :logger
4
+
5
+ def initialize(delay)
6
+ @delay = delay
6
7
  end
7
8
 
8
9
  # Called before a reattempt to sleep a certain about of time.
9
10
  def sleep
10
- log_delay
11
+ log
11
12
  Kernel.sleep(@delay)
12
13
  end
13
14
 
14
15
  # Logs how long the delay is.
15
- def log_delay
16
- @logger.debug "[Delayer] delaying for #{self}"
16
+ def log
17
+ return if @logger.nil?
18
+
19
+ @logger.debug("Delayer") { "delaying for #{self}" }
17
20
  end
18
21
 
19
22
  # Returns a string representation of the delay.
@@ -2,15 +2,21 @@ require "timeout"
2
2
  require "logger"
3
3
  require "forwardable"
4
4
 
5
- require File.expand_path("../loggers/base", __FILE__)
6
- require File.expand_path("../loggers/debug", __FILE__)
7
- require File.expand_path("../counters/base", __FILE__)
8
- require File.expand_path("../delayers/base", __FILE__)
9
- require File.expand_path("../delayers/regular", __FILE__)
10
- require File.expand_path("../delayers/exponential", __FILE__)
11
- require File.expand_path("../testers/base", __FILE__)
12
- require File.expand_path("../testers/passive", __FILE__)
13
- require File.expand_path("../testers/truthy", __FILE__)
14
- require File.expand_path("../rescuers/base", __FILE__)
15
- require File.expand_path("../raisers/base", __FILE__)
16
- require File.expand_path("../raisers/passive", __FILE__)
5
+ paths = %w(
6
+ version
7
+ loggers/base
8
+ loggers/debug
9
+ counters/base
10
+ delayers/base
11
+ delayers/regular
12
+ delayers/exponential
13
+ testers/base
14
+ testers/passive
15
+ testers/truthy
16
+ rescuers/base
17
+ raisers/base
18
+ raisers/passive
19
+ raisers/signal
20
+ )
21
+
22
+ paths.each { |path| require File.expand_path("../#{path}", __FILE__) }
@@ -2,12 +2,12 @@ class Wait
2
2
  class BaseLogger
3
3
  extend Forwardable
4
4
 
5
- attr_reader :logger
5
+ attr_reader :logger
6
6
  def_delegators :logger, :fatal,
7
- :error,
8
- :warn,
9
- :info,
10
- :debug
7
+ :error,
8
+ :warn,
9
+ :info,
10
+ :debug
11
11
 
12
12
  def initialize
13
13
  @logger = ::Logger.new(STDOUT)
@@ -20,13 +20,13 @@ class Wait
20
20
  end
21
21
 
22
22
  def formatter
23
- proc do |severity, datetime, program_name, message|
24
- [severity.ljust(5), message].join(" ") + "\n"
23
+ proc do |severity, datetime, caller, message|
24
+ "#{severity.ljust(5)} #{"[#{caller}]".ljust(9)} #{message}\n"
25
25
  end
26
26
  end
27
27
 
28
- def backtrace(backtrace)
29
- backtrace.map { |line| (" " * 25) + line }.join("\n")
28
+ def indent(lines, spaces = 25)
29
+ lines.map { |line| (" " * spaces) + line }.join("\n")
30
30
  end
31
31
  end # Logger
32
32
  end # Wait
@@ -1,18 +1,18 @@
1
1
  class Wait
2
2
  class BaseRaiser
3
- def initialize(logger, exception)
4
- @logger = logger
5
- @exception = exception
6
- log
7
- end
3
+ attr_accessor :logger
8
4
 
9
5
  # Returns +true+ if an exception ought to be raised.
10
- def raise?
11
- false
6
+ def raise?(exception)
7
+ false.tap do |raising|
8
+ log(exception, raising)
9
+ end
12
10
  end
13
11
 
14
- def log
15
- @logger.debug "[Raiser] raise? #{@exception.class.name}: #{raise?}"
12
+ def log(exception, raising)
13
+ return if @logger.nil?
14
+
15
+ @logger.debug("Raiser") { "#{"not " unless raising}raising: #{exception.class.name}" }
16
16
  end
17
17
  end # BaseRaiser
18
18
  end # Wait
@@ -0,0 +1,14 @@
1
+ class Wait
2
+ class SignalRaiser < BaseRaiser
3
+ def raise?(exception)
4
+ signal_exception?(exception.class).tap do |raising|
5
+ log(exception, raising)
6
+ end
7
+ end
8
+
9
+ # Returns +true+ if an exception raised is a signal exception.
10
+ def signal_exception?(klass)
11
+ [SignalException, Interrupt, NoMemoryError, SystemExit].include?(klass)
12
+ end
13
+ end # SignalRaiser
14
+ end # Wait
@@ -1,15 +1,23 @@
1
1
  class Wait
2
2
  class BaseRescuer
3
- attr_reader :exceptions
3
+ attr_accessor :logger
4
+ attr_reader :exceptions
4
5
 
5
- def initialize(logger, *exceptions)
6
- @logger = logger
6
+ def initialize(exceptions)
7
7
  @exceptions = Array(exceptions).flatten
8
8
  end
9
9
 
10
10
  # Logs an exception.
11
11
  def log(exception)
12
- @logger.debug "[Rescuer] rescued: #{exception.class.name}: #{exception.message}\n#{@logger.backtrace(exception.backtrace)}"
12
+ return if @logger.nil?
13
+
14
+ klass = exception.class.name
15
+ # We can omit the message if it's identical to the class name.
16
+ message = exception.message unless exception.message == klass
17
+ # Indent the exception so it stands apart from the rest of the messages.
18
+ backtrace = @logger.indent(exception.backtrace)
19
+
20
+ @logger.debug("Rescuer") { "rescued: #{klass}#{": #{message}" if message}\n#{backtrace}" }
13
21
  end
14
22
  end # BaseRescuer
15
23
  end # Wait
@@ -1,18 +1,18 @@
1
1
  class Wait
2
2
  class BaseTester
3
- def initialize(logger, result)
4
- @logger = logger
5
- @result = result
6
- log
7
- end
3
+ attr_accessor :logger
8
4
 
9
5
  # Returns +true+ if a result if valid.
10
- def valid?
6
+ def valid?(result)
7
+ log(result)
8
+
11
9
  true
12
10
  end
13
11
 
14
- def log
15
- @logger.debug "[Tester] result: #{@result.inspect}"
12
+ def log(result)
13
+ return if @logger.nil?
14
+
15
+ @logger.debug("Tester") { "result: #{result.inspect}" }
16
16
  end
17
17
  end # BaseTester
18
18
  end # Wait
@@ -1,7 +1,9 @@
1
1
  class Wait
2
2
  class TruthyTester < BaseTester
3
- def valid?
4
- not (@result.nil? or @result == false)
3
+ def valid?(result)
4
+ log(result)
5
+
6
+ not (result.nil? or result == false)
5
7
  end
6
8
  end # TruthyTester
7
9
  end # Wait
@@ -0,0 +1,3 @@
1
+ class Wait
2
+ VERSION = "0.5"
3
+ end # Wait
@@ -9,7 +9,7 @@ class Wait
9
9
  :delayer => RegularDelayer,
10
10
  :rescuer => BaseRescuer,
11
11
  :tester => TruthyTester,
12
- :raiser => PassiveRaiser,
12
+ :raiser => SignalRaiser,
13
13
  :logger => BaseLogger
14
14
  }
15
15
 
@@ -43,20 +43,26 @@ class Wait
43
43
  # Strategy used to test the result. Default is Wait::TruthyTester.
44
44
  # [:raiser]
45
45
  # Strategy used to raise specific exceptions. Default is
46
- # Wait::PassiveRaiser.
46
+ # Wait::SignalRaiser.
47
47
  #
48
48
  def initialize(options = {})
49
- debug = options[:debug] || false
50
- @logger = (options[:logger] || (debug ? DebugLogger : DEFAULT[:logger])).new
51
- attempts = options[:attempts] || DEFAULT[:attempts]
52
- @counter = (options[:counter] || DEFAULT[:counter]).new(@logger, attempts)
53
- @timeout = options[:timeout] || DEFAULT[:timeout]
54
- delay = options[:delay] || DEFAULT[:delay]
55
- @delayer = (options[:delayer] || DEFAULT[:delayer]).new(@logger, delay)
56
- exceptions = options[:rescue]
57
- @rescuer = (options[:rescuer] || DEFAULT[:rescuer]).new(@logger, exceptions)
58
- @tester = options[:tester] || DEFAULT[:tester]
59
- @raiser = options[:raiser] || DEFAULT[:raiser]
49
+ # Assign defaults.
50
+ debug = options[:debug] || false
51
+ @logger = options[:logger] || (debug ? DebugLogger : DEFAULT[:logger]).new
52
+ attempts = options[:attempts] || DEFAULT[:attempts]
53
+ @counter = options[:counter] || DEFAULT[:counter].new(attempts)
54
+ @timeout = options[:timeout] || DEFAULT[:timeout]
55
+ delay = options[:delay] || DEFAULT[:delay]
56
+ @delayer = options[:delayer] || DEFAULT[:delayer].new(delay)
57
+ exceptions = options[:rescue]
58
+ @rescuer = options[:rescuer] || DEFAULT[:rescuer].new(exceptions)
59
+ @tester = options[:tester] || DEFAULT[:tester].new
60
+ @raiser = options[:raiser] || DEFAULT[:raiser].new
61
+
62
+ # Assign the logger to each of the strategies.
63
+ [@counter, @delayer, @rescuer, @tester, @raiser].each do |strategy|
64
+ strategy.logger = @logger if strategy.respond_to?(:logger=)
65
+ end
60
66
  end
61
67
 
62
68
  # == Description
@@ -74,12 +80,12 @@ class Wait
74
80
  # # => #<Wait>
75
81
  # wait.until { Time.now.sec.even? }
76
82
  # # [Counter] attempt 1/5
77
- # # [Tester] result: false
78
- # # [Rescuer] rescued: Wait::InvalidResult: Wait::InvalidResult
79
- # # [Raiser] raise? Wait::InvalidResult: false
83
+ # # [Tester] result: false
84
+ # # [Rescuer] rescued: Wait::ResultInvalid
85
+ # # [Raiser] not raising: Wait::ResultInvalid
80
86
  # # [Delayer] delaying for 1s
81
87
  # # [Counter] attempt 2/5
82
- # # [Tester] result: true
88
+ # # [Tester] result: true
83
89
  # # => true
84
90
  #
85
91
  # If you wish to handle an exception by attempting the block again, pass one
@@ -95,16 +101,16 @@ class Wait
95
101
  # end
96
102
  # end
97
103
  # # [Counter] attempt 1/5
98
- # # [Tester] result: nil
99
- # # [Rescuer] rescued: Wait::InvalidResult: Wait::InvalidResult
100
- # # [Raiser] raise? Wait::InvalidResult: false
104
+ # # [Tester] result: nil
105
+ # # [Rescuer] rescued: Wait::ResultInvalid
106
+ # # [Raiser] not raising: Wait::ResultInvalid
101
107
  # # [Delayer] delaying for 1s
102
108
  # # [Counter] attempt 2/5
103
- # # [Rescuer] rescued: RuntimeError: RuntimeError
104
- # # [Raiser] raise? RuntimeError: false
109
+ # # [Rescuer] rescued: RuntimeError
110
+ # # [Raiser] not raising: RuntimeError
105
111
  # # [Delayer] delaying for 1s
106
112
  # # [Counter] attempt 3/5
107
- # # [Tester] result: "foo"
113
+ # # [Tester] result: "foo"
108
114
  # # => "foo"
109
115
  #
110
116
  # == Returns
@@ -127,14 +133,12 @@ class Wait
127
133
  yield(@counter.attempt)
128
134
  end
129
135
  # Raise an exception unless the result is valid.
130
- tester = @tester.new(@logger, result)
131
- tester.valid? ? result : raise(InvalidResult)
132
- rescue TimeoutError, InvalidResult, *@rescuer.exceptions => exception
136
+ @tester.valid?(result) ? result : raise(ResultInvalid)
137
+ rescue TimeoutError, ResultInvalid, *@rescuer.exceptions => exception
133
138
  # Log the exception.
134
139
  @rescuer.log(exception)
135
140
  # Raise the exception if it ought to be.
136
- raiser = @raiser.new(@logger, exception)
137
- raise(exception) if raiser.raise?
141
+ raise(exception) if @raiser.raise?(exception)
138
142
  # Raise the exception if this was the last attempt.
139
143
  raise(exception) if @counter.last_attempt?
140
144
  # Sleep before the next attempt.
@@ -148,5 +152,5 @@ class Wait
148
152
  class TimeoutError < Timeout::Error; end
149
153
 
150
154
  # Raised when a block returns an invalid result.
151
- class InvalidResult < RuntimeError; end
155
+ class ResultInvalid < RuntimeError; end
152
156
  end #Wait
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wait
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: '0.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -26,10 +26,12 @@ files:
26
26
  - lib/loggers/debug.rb
27
27
  - lib/raisers/base.rb
28
28
  - lib/raisers/passive.rb
29
+ - lib/raisers/signal.rb
29
30
  - lib/rescuers/base.rb
30
31
  - lib/testers/base.rb
31
32
  - lib/testers/passive.rb
32
33
  - lib/testers/truthy.rb
34
+ - lib/version.rb
33
35
  - lib/wait.rb
34
36
  homepage: http://github.com/paperlesspost/wait
35
37
  licenses: []