diff --git a/README.md b/README.md index 92a018d4..8d5a92f3 100644 --- a/README.md +++ b/README.md @@ -640,6 +640,8 @@ Solid Queue supports defining recurring tasks that run at specific times in the bin/jobs --recurring_schedule_file=config/schedule.yml ``` +It's also possible to define recurring tasks in several configuration files, for that specify a pattern of recurring tasks via `SolidQueue.recurring_config_file_pattern`. + You can completely disable recurring tasks by setting the environment variable `SOLID_QUEUE_SKIP_RECURRING=true` or by using the `--skip-recurring` option with `bin/jobs`. The configuration itself looks like this: diff --git a/lib/solid_queue.rb b/lib/solid_queue.rb index e0d51c8c..197fe71e 100644 --- a/lib/solid_queue.rb +++ b/lib/solid_queue.rb @@ -41,6 +41,8 @@ module SolidQueue mattr_accessor :clear_finished_jobs_after, default: 1.day mattr_accessor :default_concurrency_control_period, default: 3.minutes + mattr_accessor :recurring_config_file_pattern, default: SolidQueue::Configuration::DEFAULT_RECURRING_SCHEDULE_FILE_PATH + delegate :on_start, :on_stop, :on_exit, to: Supervisor [ Dispatcher, Scheduler, Worker ].each do |process| diff --git a/lib/solid_queue/configuration.rb b/lib/solid_queue/configuration.rb index a002b41d..b30bdf06 100644 --- a/lib/solid_queue/configuration.rb +++ b/lib/solid_queue/configuration.rb @@ -154,7 +154,15 @@ def processes_config def recurring_tasks_config @recurring_tasks_config ||= begin - config_from options[:recurring_schedule_file] + if options.key?(:recurring_schedule_config_pattern) + matching_configurations = Dir.glob(Rails.root.join(options[:recurring_schedule_config_pattern])) + matching_configurations + .each_with_object({}) do |config_file, recurring_configuration| + recurring_configuration.merge!(config_from config_file) + end + else + config_from options[:recurring_schedule_file] + end end end diff --git a/test/dummy/config/recurring_matching_pattern_a.yml b/test/dummy/config/recurring_matching_pattern_a.yml new file mode 100644 index 00000000..4cfcafb3 --- /dev/null +++ b/test/dummy/config/recurring_matching_pattern_a.yml @@ -0,0 +1,5 @@ +periodic_store_result_a: + class: StoreResultJob + queue: default + args: [ 42, { status: "custom_status" } ] + schedule: every second diff --git a/test/dummy/config/recurring_matching_pattern_b.yml b/test/dummy/config/recurring_matching_pattern_b.yml new file mode 100644 index 00000000..3d5cb407 --- /dev/null +++ b/test/dummy/config/recurring_matching_pattern_b.yml @@ -0,0 +1,5 @@ +periodic_store_result_b: + class: StoreResultJob + queue: default + args: [ 42, { status: "custom_status" } ] + schedule: every second diff --git a/test/unit/configuration_test.rb b/test/unit/configuration_test.rb index 2ccaa728..5f06416c 100644 --- a/test/unit/configuration_test.rb +++ b/test/unit/configuration_test.rb @@ -68,6 +68,7 @@ class ConfigurationTest < ActiveSupport::TestCase assert_processes configuration, :scheduler, 1 scheduler = configuration.configured_processes.second.instantiate + assert_equal 1, scheduler.recurring_schedule.configured_tasks.count assert_has_recurring_task scheduler, key: "periodic_store_result", class_name: "StoreResultJob", schedule: "every second" end @@ -77,6 +78,7 @@ class ConfigurationTest < ActiveSupport::TestCase assert_processes configuration, :scheduler, 1 scheduler = configuration.configured_processes.first.instantiate + assert_equal 1, scheduler.recurring_schedule.configured_tasks.count assert_has_recurring_task scheduler, key: "periodic_store_result", class_name: "StoreResultJob", schedule: "every second" end @@ -143,6 +145,20 @@ class ConfigurationTest < ActiveSupport::TestCase configuration.errors.full_messages.first end + test "multiple recurring configuration files" do + configuration = SolidQueue::Configuration.new(recurring_schedule_config_pattern: "config/recurring_matching_pattern_*.yml") + + assert configuration.valid? + assert_processes configuration, :scheduler, 1 + + scheduler = configuration.configured_processes.find { |process| process.kind == :scheduler }.instantiate + + assert_equal 2, scheduler.recurring_schedule.configured_tasks.count + assert_has_recurring_task scheduler, key: "periodic_store_result_a", class_name: "StoreResultJob", schedule: "every second" + assert_has_recurring_task scheduler, key: "periodic_store_result_b", class_name: "StoreResultJob", schedule: "every second" + ensure + end + private def assert_processes(configuration, kind, count, **attributes) processes = configuration.configured_processes.select { |p| p.kind == kind } @@ -159,7 +175,6 @@ def assert_processes(configuration, kind, count, **attributes) end def assert_has_recurring_task(scheduler, key:, **attributes) - assert_equal 1, scheduler.recurring_schedule.configured_tasks.count task = scheduler.recurring_schedule.configured_tasks.detect { |t| t.key == key } attributes.each do |attr, value|