Class: Vmpooler::AdaptiveTimeout

Inherits:
Object
  • Object
show all
Defined in:
lib/vmpooler/adaptive_timeout.rb

Overview

Adaptive timeout that adjusts based on observed connection performance to optimize between responsiveness and reliability.

Tracks recent connection durations and adjusts timeout to p95 + buffer, reducing timeout on failures to fail faster during outages.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, logger:, metrics:, min: 5, max: 60, initial: 30, max_samples: 100) ⇒ AdaptiveTimeout

Initialize adaptive timeout

Parameters:

  • name (String)

    Name for logging (e.g., "vsphere_connections")

  • logger (Object)

    Logger instance

  • metrics (Object)

    Metrics instance

  • min (Integer) (defaults to: 5)

    Minimum timeout in seconds

  • max (Integer) (defaults to: 60)

    Maximum timeout in seconds

  • initial (Integer) (defaults to: 30)

    Initial timeout in seconds

  • max_samples (Integer) (defaults to: 100)

    Number of recent samples to track



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/vmpooler/adaptive_timeout.rb', line 21

def initialize(name:, logger:, metrics:, min: 5, max: 60, initial: 30, max_samples: 100)
  @name = name
  @logger = logger
  @metrics = metrics
  @min_timeout = min
  @max_timeout = max
  @current_timeout = initial
  @recent_durations = []
  @max_samples = max_samples
  @mutex = Mutex.new
end

Instance Attribute Details

#current_timeoutObject (readonly)

Returns the value of attribute current_timeout.



10
11
12
# File 'lib/vmpooler/adaptive_timeout.rb', line 10

def current_timeout
  @current_timeout
end

Instance Method Details

#record_failureObject

Record a failure (timeout or error) Reduces current timeout to fail faster on subsequent attempts



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/vmpooler/adaptive_timeout.rb', line 53

def record_failure
  @mutex.synchronize do
    old_timeout = @current_timeout
    # Reduce timeout by 20% on failure, but don't go below minimum
    @current_timeout = [(@current_timeout * 0.8).round, @min_timeout].max

    if old_timeout != @current_timeout
      @logger.log('d', "[*] [adaptive_timeout] '#{@name}' reduced timeout #{old_timeout}s → #{@current_timeout}s after failure")
      @metrics.gauge("adaptive_timeout.current.#{@name}", @current_timeout)
    end
  end
end

#record_success(duration) ⇒ Object

Record a successful operation duration

Parameters:

  • duration (Float)

    Duration in seconds



41
42
43
44
45
46
47
48
49
# File 'lib/vmpooler/adaptive_timeout.rb', line 41

def record_success(duration)
  @mutex.synchronize do
    @recent_durations << duration
    @recent_durations.shift if @recent_durations.size > @max_samples

    # Adjust timeout based on recent performance
    adjust_timeout if @recent_durations.size >= 10
  end
end

#resetObject

Reset to initial timeout (useful after recovery)



67
68
69
70
71
72
73
74
75
76
# File 'lib/vmpooler/adaptive_timeout.rb', line 67

def reset
  @mutex.synchronize do
    @recent_durations.clear
    old_timeout = @current_timeout
    @current_timeout = [@max_timeout, 30].min

    @logger.log('d', "[*] [adaptive_timeout] '#{@name}' reset timeout #{old_timeout}s → #{@current_timeout}s")
    @metrics.gauge("adaptive_timeout.current.#{@name}", @current_timeout)
  end
end

#statsHash

Get statistics about recent durations

Returns:

  • (Hash)

    Statistics including min, max, avg, p95



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/vmpooler/adaptive_timeout.rb', line 80

def stats
  @mutex.synchronize do
    return { samples: 0 } if @recent_durations.empty?

    sorted = @recent_durations.sort
    {
      samples: sorted.size,
      min: sorted.first.round(2),
      max: sorted.last.round(2),
      avg: (sorted.sum / sorted.size.to_f).round(2),
      p50: percentile(sorted, 0.50).round(2),
      p95: percentile(sorted, 0.95).round(2),
      p99: percentile(sorted, 0.99).round(2),
      current_timeout: @current_timeout
    }
  end
end

#timeoutInteger

Get current timeout value (thread-safe)

Returns:

  • (Integer)

    Current timeout in seconds



35
36
37
# File 'lib/vmpooler/adaptive_timeout.rb', line 35

def timeout
  @mutex.synchronize { @current_timeout }
end