Class: DispatchPolicy::TickLoop

Inherits:
Object
  • Object
show all
Defined in:
lib/dispatch_policy/tick_loop.rb

Overview

Shared driver for DispatchTickLoopJob and any foreground tick (e.g. a rake task). Loops Tick.reap + Tick.run with an interruptible sleep and bails when stop_when returns true.

Class Method Summary collapse

Class Method Details

.interruptible_sleep(total, stop_when) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/dispatch_policy/tick_loop.rb', line 32

def self.interruptible_sleep(total, stop_when)
  return unless total.positive?

  remaining = total
  step = 0.1
  while remaining.positive?
    break if stop_when.call
    chunk = [ remaining, step ].min
    sleep(chunk)
    remaining -= chunk
  end
end

.run(policy_name: nil, sleep_for: nil, sleep_for_busy: nil, stop_when: -> { false }) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/dispatch_policy/tick_loop.rb', line 8

def self.run(policy_name: nil, sleep_for: nil, sleep_for_busy: nil, stop_when: -> { false })
  idle_sleep = (sleep_for      || DispatchPolicy.config.tick_sleep).to_f
  busy_sleep = (sleep_for_busy || DispatchPolicy.config.tick_sleep_busy).to_f

  loop do
    break if stop_when.call

    admitted = 0
    begin
      ActiveRecord::Base.uncached do
        Tick.reap
        admitted = Tick.run(policy_name: policy_name).to_i
      end
    rescue StandardError => e
      Rails.logger&.error("[DispatchPolicy] tick error: #{e.class}: #{e.message}")
      Rails.error.report(e, handled: true) if defined?(Rails) && Rails.respond_to?(:error)
    end

    break if stop_when.call

    interruptible_sleep(admitted.positive? ? busy_sleep : idle_sleep, stop_when)
  end
end