Skip to content

Commit b012535

Browse files
committed
Refactor scheduler loop and add missing tests
Keep the longer sleep interval when dynamic tasks are disabled. Add tests for `dynamic_tasks_enabled` opt-in in configuration and for verifying dynamic tasks are ignored when not enabled.
1 parent f7e39b5 commit b012535

5 files changed

Lines changed: 66 additions & 30 deletions

File tree

app/models/solid_queue/recurring_task.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class RecurringTask < Record
2020

2121
class << self
2222
def wrap(args)
23-
args.is_a?(self) ? args : from_configuration(args.first, **args.second.reverse_merge(static: true))
23+
args.is_a?(self) ? args : from_configuration(args.first, **args.second)
2424
end
2525

2626
def from_configuration(key, **options)
@@ -33,7 +33,7 @@ def from_configuration(key, **options)
3333
queue_name: options[:queue].presence,
3434
priority: options[:priority].presence,
3535
description: options[:description],
36-
static: !!options[:static]
36+
static: options.fetch(:static, true)
3737
end
3838

3939
def create_or_update_all(tasks)

lib/solid_queue/configuration.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ def dispatchers
144144
def schedulers
145145
return [] if skip_recurring_tasks?
146146

147-
if recurring_tasks.any? || dynamic_tasks_enabled?
148-
[ Process.new(:scheduler, { recurring_tasks:, **scheduler_options.with_defaults(SCHEDULER_DEFAULTS) }) ]
147+
if recurring_tasks.any? || dynamic_recurring_tasks_enabled?
148+
[ Process.new(:scheduler, { recurring_tasks: recurring_tasks, **scheduler_options.with_defaults(SCHEDULER_DEFAULTS) }) ]
149149
else
150150
[]
151151
end
@@ -165,7 +165,7 @@ def scheduler_options
165165
@scheduler_options ||= processes_config.fetch(:scheduler, {}).dup.symbolize_keys
166166
end
167167

168-
def dynamic_tasks_enabled?
168+
def dynamic_recurring_tasks_enabled?
169169
scheduler_options.fetch(:dynamic_tasks_enabled, SCHEDULER_DEFAULTS[:dynamic_tasks_enabled])
170170
end
171171

lib/solid_queue/scheduler.rb

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class Scheduler < Processes::Base
1515

1616
def initialize(recurring_tasks:, **options)
1717
options = options.dup.with_defaults(SolidQueue::Configuration::SCHEDULER_DEFAULTS)
18-
@dynamic_tasks = options[:dynamic_tasks_enabled]
18+
@dynamic_tasks_enabled = options[:dynamic_tasks_enabled]
1919
@polling_interval = options[:polling_interval]
20-
@recurring_schedule = RecurringSchedule.new(recurring_tasks, dynamic_tasks_enabled: @dynamic_tasks)
20+
@recurring_schedule = RecurringSchedule.new(recurring_tasks, dynamic_tasks_enabled: @dynamic_tasks_enabled)
2121

2222
super(**options)
2323
end
@@ -27,35 +27,20 @@ def metadata
2727
end
2828

2929
private
30-
attr_reader :dynamic_tasks
3130

32-
def run
33-
if dynamic_tasks
34-
poll_for_dynamic_tasks
35-
else
36-
loop do
37-
break if shutting_down?
38-
interruptible_sleep(polling_interval)
39-
end
40-
end
41-
ensure
42-
SolidQueue.instrument(:shutdown_process, process: self) do
43-
run_callbacks(:shutdown) { shutdown }
44-
end
45-
end
31+
STATIC_SLEEP_INTERVAL = 60
4632

47-
def poll_for_dynamic_tasks
33+
def run
4834
loop do
4935
break if shutting_down?
5036

51-
recurring_schedule.reload!
52-
53-
if recurring_schedule.changed?
54-
refresh_registered_process
55-
recurring_schedule.clear_changes
56-
end
37+
reload_schedule if dynamic_tasks_enabled?
5738

58-
interruptible_sleep(polling_interval)
39+
interruptible_sleep(sleep_interval)
40+
end
41+
ensure
42+
SolidQueue.instrument(:shutdown_process, process: self) do
43+
run_callbacks(:shutdown) { shutdown }
5944
end
6045
end
6146

@@ -67,10 +52,27 @@ def unschedule_recurring_tasks
6752
recurring_schedule.unschedule_tasks
6853
end
6954

55+
def reload_schedule
56+
recurring_schedule.reload!
57+
58+
if recurring_schedule.changed?
59+
refresh_registered_process
60+
recurring_schedule.clear_changes
61+
end
62+
end
63+
64+
def dynamic_tasks_enabled?
65+
@dynamic_tasks_enabled
66+
end
67+
7068
def all_work_completed?
7169
recurring_schedule.empty?
7270
end
7371

72+
def sleep_interval
73+
dynamic_tasks_enabled? ? polling_interval : STATIC_SLEEP_INTERVAL
74+
end
75+
7476
def set_procline
7577
procline "scheduling #{recurring_schedule.task_keys.join(",")}"
7678
end

test/unit/configuration_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@ class ConfigurationTest < ActiveSupport::TestCase
8787
assert_has_recurring_task scheduler, key: "periodic_store_result", class_name: "StoreResultJob", schedule: "every second"
8888
end
8989

90+
test "scheduler starts with dynamic_tasks_enabled even without static tasks" do
91+
configuration = SolidQueue::Configuration.new(
92+
recurring_schedule_file: config_file_path(:empty_configuration),
93+
scheduler: { dynamic_tasks_enabled: true }
94+
)
95+
96+
assert_processes configuration, :scheduler, 1, dynamic_tasks_enabled: true
97+
end
98+
99+
test "no scheduler without static tasks or dynamic_tasks_enabled" do
100+
configuration = SolidQueue::Configuration.new(
101+
recurring_schedule_file: config_file_path(:empty_configuration),
102+
scheduler: { dynamic_tasks_enabled: false }
103+
)
104+
105+
assert_processes configuration, :scheduler, 0
106+
end
107+
90108
test "no recurring tasks configuration when explicitly excluded" do
91109
configuration = SolidQueue::Configuration.new(dispatchers: [ { polling_interval: 0.1 } ], skip_recurring: true)
92110
assert_processes configuration, :dispatcher, 1, polling_interval: 0.1, recurring_tasks: nil

test/unit/scheduler_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ class SchedulerTest < ActiveSupport::TestCase
5252
scheduler.stop
5353
end
5454

55+
test "dynamic tasks in DB are ignored when dynamic_tasks_enabled is false" do
56+
SolidQueue::RecurringTask.create!(
57+
key: "ignored_task", static: false, class_name: "AddToBufferJob", schedule: "every second", arguments: [ 42 ]
58+
)
59+
60+
recurring_tasks = { static_task: { class: "AddToBufferJob", schedule: "every hour", args: 42 } }
61+
scheduler = SolidQueue::Scheduler.new(recurring_tasks: recurring_tasks).tap(&:start)
62+
63+
wait_for_registered_processes(1, timeout: 1.second)
64+
65+
process = SolidQueue::Process.first
66+
assert_metadata process, recurring_schedule: [ "static_task" ]
67+
ensure
68+
scheduler.stop
69+
end
70+
5571
test "run more than one instance of the scheduler with recurring tasks" do
5672
recurring_tasks = { example_task: { class: "AddToBufferJob", schedule: "every second", args: 42 } }
5773
schedulers = 2.times.collect do

0 commit comments

Comments
 (0)