Class: InfluxDB2::WriteRetry

Inherits:
Object
  • Object
show all
Defined in:
lib/influxdb2/client/write_retry.rb

Overview

Exponential random write retry.

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ WriteRetry

Returns a new instance of WriteRetry.

Parameters:

  • options (Hash) (defaults to: {})

    the retry options.

Options Hash (options):

  • :max_retries (Integer) — default: 5

    The maximum number of times to run the block.

  • :retry_interval (Integer) — default: 5000

    number of milliseconds to retry unsuccessful write.

  • :max_retry_delay (Integer) — default: 125_000

    maximum delay when retrying write in milliseconds.

  • :max_retry_time (Integer) — default: 180_000

    maximum total retry timeout in milliseconds.

  • :exponential_base (Integer)

    base for the exponential retry delay

  • :jitter_delay (Integer)

    random milliseconds added to write interval



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/influxdb2/client/write_retry.rb', line 33

def initialize(options = {})
  @api_client = options[:api_client]
  @max_retries = options[:max_retries] || 5
  raise "#{@error_msg_prefix} :max_retries must be greater than 0." unless @max_retries > 0

  @retry_interval = options[:retry_interval] || 5_000
  @max_retry_delay = options[:max_retry_delay] || 125_000
  @max_retry_time = options[:max_retry_time] || 180_000
  @exponential_base = options[:exponential_base] || 2
  @jitter_interval = options[:jitter_interval] || 0
  raise "#{@error_msg_prefix} :retry_interval cannot be greater than :max_retry_delay." if
    @retry_interval > @max_retry_delay
end

Instance Method Details

#_connection_error(error) ⇒ Object



100
101
102
# File 'lib/influxdb2/client/write_retry.rb', line 100

def _connection_error(error)
  InfluxError::HTTP_ERRORS.any? { |c| error.instance_of? c }
end

#get_backoff_time(attempts) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/influxdb2/client/write_retry.rb', line 47

def get_backoff_time(attempts)
  range_start = @retry_interval
  range_stop = @retry_interval * @exponential_base

  i = 1
  while i < attempts
    i += 1
    range_start = range_stop
    range_stop *= @exponential_base
    break if range_stop > @max_retry_delay
  end

  range_stop = @max_retry_delay if range_stop > @max_retry_delay
  range_start + (range_stop - range_start) * rand
end

#retryObject

Runs the supplied code block with a exponential backoff retry strategy.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/influxdb2/client/write_retry.rb', line 64

def retry
  raise "#{@error_msg_prefix} must be passed a block" unless block_given?

  attempts = 0
  start_time = Time.now
  begin
    attempts += 1
    yield attempts
  rescue InfluxError => e
    if attempts > @max_retries
      @api_client.log(:error, 'Maximum retry attempts reached.')
      raise e
    end

    if (Time.now - start_time) * 1000 > @max_retry_time
      @api_client.log(:error, "Maximum retry time #{@max_retry_time} ms exceeded")
      raise e
    end

    raise e if (e.code.nil? || e.code.to_i < 429) && !_connection_error(e.original)

    timeout = if e.retry_after.nil? || e.retry_after.empty?
                get_backoff_time(attempts)
              else
                (e.retry_after.to_f * 1000) + @jitter_interval * rand
              end

    message = 'The retriable error occurred during writing of data. '\
"Reason: '#{e.message}'. Retry in: #{timeout.to_f / 1000}s."

    @api_client.log(:warn, message)
    sleep timeout / 1000
    retry
  end
end