class BitGirder::Concurrent::Retry

Attributes

attempt[R]
start_time[R]

Public Class Methods

new( *argv ) { |bldr| ... } click to toggle source
# File lib/bitgirder/concurrent.rb, line 220
def initialize( *argv )
 
    super
    BitGirder::Concurrent.require_em

    @bldr = Builder.new
    yield @bldr if block_given?
    @bldr.freeze

    [ :retries, :seed_secs, :retry_on ].each do |m|
        raise ":#{m} not set" unless @bldr.instance_variable_get( :"@#{m}" )
    end

    if @bldr.action || @bldr.async_action
        if @bldr.action && @bldr.async_action
            raise "Both a synchronous and asynchronous action were set"
        end
    else
        raise "Neither :action nor :async_action was set"
    end

    @attempt = 0
end
run( *argv, &blk ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 359
def Retry.run( *argv, &blk )
    Retry.new( *argv, &blk ).run
end

Public Instance Methods

complete( res = nil ) { || ... } click to toggle source

Callback for an async action

# File lib/bitgirder/concurrent.rb, line 309
def complete( res = nil )
    
    if block_given?

        if res == nil
            begin
                complete_final( yield ) # okay for yield to return nil
            rescue Exception => e
                action_failed( e )
            end
        else
            raise "Block passed to complete with non-nil result: #{res}"
        end
    else
        complete_final( res )
    end
end
fail_attempt( err ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 328
def fail_attempt( err )
    complete { raise err }
end
run() click to toggle source
# File lib/bitgirder/concurrent.rb, line 349
def run
    
    if @start_time
        raise "run() already called"
    else
        @start_time = Time.now
        run_attempt
    end
end
seed_secs() click to toggle source
# File lib/bitgirder/concurrent.rb, line 245
def seed_secs
    @bldr.seed_secs
end

Private Instance Methods

action_failed( err ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 292
def action_failed( err )
    
    if res = should_retry?( err )
        
        if @attempt == @bldr.retries
            fail_final( err )
        else
            dur = @bldr.seed_secs * ( 1 << ( @attempt - 1 ) )
            EM.add_timer( dur ) { run_attempt }
        end
    else
        fail_final( err )
    end
end
complete_final( res ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 279
def complete_final( res )
    
    if @bldr.complete
        
        begin
            invoke_call( res, @bldr.complete, "block :complete" )
        rescue Exception => e 
            fail_final( e )
        end
    end
end
fail_final( err ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 274
def fail_final( err )
    invoke_call( err, @bldr.failed, "block :failed" )
end
invoke_call( val, call, name ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 260
def invoke_call( val, call, name )
        
    args = 
        case arity = call.arity
            when 0, -1 then []
            when 1 then [ val ]
            when 2 then [ self, val ]
            else raise "Unexpected arity in #{name}: #{arity}"
        end

    call.call( *args )
end
run_attempt() click to toggle source
# File lib/bitgirder/concurrent.rb, line 333
def run_attempt

    @attempt += 1

    begin
        if @bldr.action
            complete_final( @bldr.action.call( self ) )
        else
            @bldr.async_action.call( self )
        end
    rescue Exception => e
        action_failed( e )
    end
end
should_retry?( err ) click to toggle source
# File lib/bitgirder/concurrent.rb, line 250
def should_retry?( err )
    
    case val = @bldr.instance_variable_get( :@retry_on )

        when Array then val.find { |err_cls| err.is_a?( err_cls ) }
        else val.call( err )
    end
end