Module: Webhookdb::Async::Autoscaler

Includes:
Appydays::Configurable, Appydays::Loggable
Defined in:
lib/webhookdb/async/autoscaler.rb

Defined Under Namespace

Classes: FakeImplementation

Constant Summary collapse

AVAILABLE_PROVIDERS =
["heroku", "fake"].freeze

Class Method Summary collapse

Class Method Details

._alert_sentry_latency(kw) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'lib/webhookdb/async/autoscaler.rb', line 86

def _alert_sentry_latency(kw)
  call_sentry = @last_called_sentry.nil? ||
    @last_called_sentry < (Time.now - self.sentry_alert_interval)
  return unless call_sentry
  Sentry.with_scope do |scope|
    scope&.set_extras(**kw)
    Sentry.capture_message("Some queues have a high latency")
  end
  @last_called_sentry = Time.now
end

._check_provider!Object



14
15
16
17
18
# File 'lib/webhookdb/async/autoscaler.rb', line 14

def self._check_provider!
  return if AVAILABLE_PROVIDERS.include?(self.provider)
  return if !self.enabled && self.provider.blank?
  raise "invalid AUTOSCALER_PROVIDER: '#{self.provider}', one of: #{AVAILABLE_PROVIDERS.join(', ')}"
end

.build_implementationObject



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/webhookdb/async/autoscaler.rb', line 41

def build_implementation
  case self.provider
    when "heroku"
      opts = {heroku: Webhookdb::Heroku.client, max_additional_workers: self.max_additional_workers}
      (opts[:app_id_or_app_name] = self.heroku_app_id_or_app_name) if
        self.heroku_app_id_or_app_name.present?
      (opts[:formation_id_or_formation_type] = self.heroku_formation_id_or_formation_type) if
        self.heroku_formation_id_or_formation_type.present?
      return Amigo::Autoscaler::Heroku.new(**opts)
    when "fake"
      return FakeImplementation.new
    else
      self._check_provider!
  end
end

.enabled?Boolean

Returns:

  • (Boolean)


39
# File 'lib/webhookdb/async/autoscaler.rb', line 39

def enabled? = self.enabled

.scale_down(depth:, duration:) ⇒ Object



97
98
99
100
# File 'lib/webhookdb/async/autoscaler.rb', line 97

def scale_down(depth:, duration:, **)
  scale_action = @impl.scale_down(depth:, duration:, **)
  self.logger.warn("high_latency_queues_resolved", depth:, duration:, scale_action:)
end

.scale_up(names_and_latencies, depth:, duration:) ⇒ Object



79
80
81
82
83
84
# File 'lib/webhookdb/async/autoscaler.rb', line 79

def scale_up(names_and_latencies, depth:, duration:, **)
  scale_action = @impl.scale_up(names_and_latencies, depth:, duration:, **)
  kw = {queues: names_and_latencies, depth:, duration:, scale_action:}
  self.logger.warn("high_latency_queues_event", **kw)
  self._alert_sentry_latency(kw)
end

.startObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/webhookdb/async/autoscaler.rb', line 57

def start
  raise "already started" unless @instance.nil?
  @impl = self.build_implementation
  @instance = Amigo::Autoscaler.new(
    poll_interval: self.poll_interval,
    latency_threshold: self.latency_threshold,
    hostname_regex: self.hostname_regex,
    handlers: [self.method(:scale_up)],
    alert_interval: self.alert_interval,
    latency_restored_threshold: self.latency_restored_threshold,
    latency_restored_handlers: [self.method(:scale_down)],
    log: ->(level, msg, kw={}) { self.logger.send(level, msg, kw) },
    on_unhandled_exception: ->(e) { Sentry.capture_exception(e) },
  )
  return @instance.start
end

.stopObject



74
75
76
77
# File 'lib/webhookdb/async/autoscaler.rb', line 74

def stop
  raise "not started" if @instance.nil?
  @instance.stop
end