diff --git a/lib/solid_queue/scheduler/recurring_schedule.rb b/lib/solid_queue/scheduler/recurring_schedule.rb index 526a8edc..36cdc231 100644 --- a/lib/solid_queue/scheduler/recurring_schedule.rb +++ b/lib/solid_queue/scheduler/recurring_schedule.rb @@ -48,8 +48,10 @@ def task_keys def reschedule_dynamic_tasks wrap_in_app_executor do + previous_tasks = dynamic_tasks.index_by(&:key) reload_dynamic_tasks schedule_created_dynamic_tasks + reschedule_updated_dynamic_tasks(previous_tasks) unschedule_deleted_dynamic_tasks end end @@ -75,6 +77,16 @@ def schedule_created_dynamic_tasks end end + def reschedule_updated_dynamic_tasks(previous_tasks) + dynamic_tasks.each do |task| + previous_task = previous_tasks[task.key] + next if previous_task.nil? || previous_task.updated_at == task.updated_at + + scheduled_tasks[task.key]&.cancel + schedule_task(task) + end + end + def unschedule_deleted_dynamic_tasks (scheduled_tasks.keys - RecurringTask.pluck(:key)).each do |key| scheduled_tasks[key].cancel diff --git a/test/unit/scheduler_test.rb b/test/unit/scheduler_test.rb index e914a23c..241501e9 100644 --- a/test/unit/scheduler_test.rb +++ b/test/unit/scheduler_test.rb @@ -131,6 +131,26 @@ class SchedulerTest < ActiveSupport::TestCase scheduler&.stop end + test "picks up updates to dynamic tasks post-start" do + task = SolidQueue::RecurringTask.create!( + key: "updatable_task", static: false, class_name: "AddToBufferJob", schedule: "every hour", arguments: [ 42 ] + ) + + scheduler = SolidQueue::Scheduler.new(recurring_tasks: {}, dynamic_tasks_enabled: true, polling_interval: 0.1).tap(&:start) + + wait_for_registered_processes(1, timeout: 1.second) + + task.update!(schedule: "every second") + + wait_while_with_timeout(3.seconds) { SolidQueue::Job.count < 1 } + + skip_active_record_query_cache do + assert SolidQueue::Job.count >= 1, "Expected the updated schedule to enqueue jobs without a scheduler restart" + end + ensure + scheduler&.stop + end + test "updates metadata after removing dynamic task post-start" do old_dynamic_task = SolidQueue::RecurringTask.create!( key: "old_dynamic_task",