lib/attempt.rb in attempt-0.6.1 vs lib/attempt.rb in attempt-0.6.2

- old
+ new

@@ -1,14 +1,20 @@ -require 'safe_timeout' +# frozen_string_literal: true + +if File::ALT_SEPARATOR + require 'timeout' +else + require 'safe_timeout' +end + require 'structured_warnings' # The Attempt class encapsulates methods related to multiple attempts at # running the same method before actually failing. class Attempt - # The version of the attempt library. - VERSION = '0.6.1'.freeze + VERSION = '0.6.2' # Warning raised if an attempt fails before the maximum number of tries # has been reached. class Warning < StructuredWarnings::StandardWarning; end @@ -49,11 +55,11 @@ # * increment - The amount to increment the interval between tries. The default is 0. # * level - The level of exception to be caught. The default is everything, i.e. Exception. # * warnings - Boolean value that indicates whether or not errors are treated as warnings # until the maximum number of attempts has been made. The default is true. # * timeout - Boolean value to indicate whether or not to automatically wrap your - # proc in a SafeTimeout block. The default is false. + # proc in a Timeout/SafeTimeout block. The default is false. # # Example: # # a = Attempt.new(tries: 5, increment: 10, timeout: true) # a.attempt{ http.get("http://something.foo.com") } @@ -72,22 +78,22 @@ # times, sleeping +interval+ between each try. # # You will not typically use this method directly, but the Kernel#attempt # method instead. # - def attempt + def attempt(&block) count = 1 begin if @timeout - SafeTimeout.timeout(@timeout){ yield } + File::ALT_SEPARATOR ? Timeout.timeout(@timeout, &block) : SafeTimeout.timeout(@timeout, &block) else yield end - rescue @level => error + rescue @level => err @tries -= 1 if @tries > 0 - msg = "Error on attempt # #{count}: #{error}; retrying" + msg = "Error on attempt # #{count}: #{err}; retrying" count += 1 warn Warning, msg if @warnings if @log # Accept an IO or Logger object @log.respond_to?(:puts) ? @log.puts(msg) : @log.warn(msg) @@ -100,32 +106,33 @@ raise end end end +# Extend the Kernel module with a simple interface for the Attempt class. module Kernel - # :call-seq: - # attempt(tries: 3, interval: 60, timeout: 10){ # some op } - # - # Attempt to perform the operation in the provided block up to +tries+ - # times, sleeping +interval+ between each try. By default the number - # of tries defaults to 3, the interval defaults to 60 seconds, and there - # is no timeout specified. - # - # If +timeout+ is provided then the operation is wrapped in a Timeout - # block as well. This is handy for those rare occasions when an IO - # connection could hang indefinitely, for example. - # - # If the operation still fails the (last) error is then re-raised. - # - # This is really just a convenient wrapper for Attempt.new + Attempt#attempt. - # - # Example: - # - # # Make 3 attempts to connect to the database, 60 seconds apart. - # attempt{ DBI.connect(dsn, user, passwd) } - # - def attempt(**kwargs, &block) - object = Attempt.new(kwargs) - object.attempt(&block) - end + # :call-seq: + # attempt(tries: 3, interval: 60, timeout: 10){ # some op } + # + # Attempt to perform the operation in the provided block up to +tries+ + # times, sleeping +interval+ between each try. By default the number + # of tries defaults to 3, the interval defaults to 60 seconds, and there + # is no timeout specified. + # + # If +timeout+ is provided then the operation is wrapped in a Timeout + # block as well. This is handy for those rare occasions when an IO + # connection could hang indefinitely, for example. + # + # If the operation still fails the (last) error is then re-raised. + # + # This is really just a convenient wrapper for Attempt.new + Attempt#attempt. + # + # Example: + # + # # Make 3 attempts to connect to the database, 60 seconds apart. + # attempt{ DBI.connect(dsn, user, passwd) } + # + def attempt(**kwargs, &block) + object = Attempt.new(**kwargs) + object.attempt(&block) + end end