Class: RailsPodKit::SolidQueue::SchedulerRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_pod_kit/solid_queue/scheduler_runner.rb

Overview

Runs a SolidQueue scheduler — and only the scheduler — as a supervised background thread, so the process running jobs can scale to zero.

Scaling the executor to zero is otherwise a chicken-and-egg problem: with no executor there is no scheduler, so nothing enqueues the recurring or scheduled jobs that would wake one. A k8s CronJob can't take over either, because it can't own dynamic recurring tasks (created and updated at runtime through SolidQueue.schedule_recurring_task). Moving just the scheduler onto an always-on process — the web, or the exporter pod — breaks the cycle: it keeps evaluating the crons and enqueueing, and the queue depth wakes the executor.

Deliberately not the full supervisor (plugin :solid_queue): that one forks, and its Puma watchdog takes the host process down when the supervisor exits — which a transient Postgres disconnect is enough to cause (rails/solid_queue#512). Here a DB blip at worst kills the scheduler thread; the supervising timer notices on its next tick and starts a fresh one, and the host process never notices.

Running it on every replica is safe: enqueues stay exactly-once via the unique index on solid_queue_recurring_executions (task_key, run_at).

Constant Summary collapse

DEFAULT_POLLING_INTERVAL =

How often the scheduler re-reads the dynamic tasks from the DB.

5
DEFAULT_SUPERVISION_INTERVAL =

How often we check that the scheduler thread is still alive.

5
SOURCE =
'rails_pod_kit.solid_queue_scheduler'

Instance Method Summary collapse

Constructor Details

#initialize(polling_interval: DEFAULT_POLLING_INTERVAL, supervision_interval: DEFAULT_SUPERVISION_INTERVAL, recurring_schedule_file: nil) ⇒ SchedulerRunner

Returns a new instance of SchedulerRunner.



40
41
42
43
44
45
46
# File 'lib/rails_pod_kit/solid_queue/scheduler_runner.rb', line 40

def initialize(polling_interval: DEFAULT_POLLING_INTERVAL,
               supervision_interval: DEFAULT_SUPERVISION_INTERVAL,
               recurring_schedule_file: nil)
  @polling_interval = polling_interval
  @supervision_interval = supervision_interval
  @recurring_schedule_file = recurring_schedule_file
end

Instance Method Details

#running?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/rails_pod_kit/solid_queue/scheduler_runner.rb', line 63

def running?
  !!@supervisor&.running?
end

#startObject

Starts the supervisor, which starts the scheduler on its first (immediate) tick and returns without blocking.



50
51
52
53
# File 'lib/rails_pod_kit/solid_queue/scheduler_runner.rb', line 50

def start
  @supervisor = build_supervisor.start
  self
end

#stopObject

Graceful stop: the supervisor drops its timer before winding the scheduler down (unschedule its timers and deregister the process, instead of leaving a row to expire).



58
59
60
61
# File 'lib/rails_pod_kit/solid_queue/scheduler_runner.rb', line 58

def stop
  @supervisor&.stop
  @supervisor = nil
end