Class: Aspera::Resumer

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/resumer.rb

Overview

implements a simple resume policy

Constant Summary collapse

DEFAULTS =

list of supported parameters and default values

{
  iter_max:      7,
  sleep_initial: 2,
  sleep_factor:  2,
  sleep_max:     60
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(params = nil) ⇒ Resumer

Returns a new instance of Resumer.

Parameters:

  • params (defaults to: nil)

    see DEFAULTS



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/aspera/resumer.rb', line 19

def initialize(params=nil)
  @parameters = DEFAULTS.dup
  if !params.nil?
    Aspera.assert_type(params, Hash)
    params.each do |k, v|
      Aspera.assert_values(k, DEFAULTS.keys){'resume parameter'}
      Aspera.assert_type(v, Integer){k}
      @parameters[k] = v
    end
  end
  Log.log.debug{"resume params=#{@parameters}"}
end

Instance Method Details

#execute_with_resumeObject

calls block a number of times (resumes) until success or limit reached this is re-entrant, one resumer can handle multiple transfers in //



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/aspera/resumer.rb', line 34

def execute_with_resume
  Aspera.assert(block_given?)
  # maximum of retry
  remaining_resumes = @parameters[:iter_max]
  sleep_seconds = @parameters[:sleep_initial]
  Log.log.debug{"retries=#{remaining_resumes}"}
  # try to send the file until ascp is successful
  loop do
    Log.log.debug('transfer starting')
    begin
      # call provided block
      yield
      # exit retry loop if success
      break
    rescue Transfer::Error => e
      Log.log.warn{"An error occurred during transfer: #{e.message}"}
      # failure in ascp
      if e.retryable?
        # exit if we exceed the max number of retry
        raise Transfer::Error, "Maximum number of retry reached (#{@parameters[:iter_max]})" if remaining_resumes <= 0
      else
        # give one chance only to non retryable errors
        unless remaining_resumes.eql?(@parameters[:iter_max])
          Log.log.error('non-retryable error'.red.blink)
          raise e
        end
      end
    end

    # take this retry in account
    remaining_resumes -= 1
    Log.log.warn{"Resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})"}

    # wait a bit before retrying, maybe network condition will be better
    sleep(sleep_seconds)

    # increase retry period
    sleep_seconds *= @parameters[:sleep_factor]
    # cap value
    sleep_seconds = @parameters[:sleep_max] if sleep_seconds > @parameters[:sleep_max]
  end
end