Skip to content

Commit 90f63c8

Browse files
committed
Allow specifying recurring tasks just with a "command"
No need to have a class, can specify this using just a command for which we'd provide a default RecurringtJob class that will just eval the command.
1 parent 8d47ed4 commit 90f63c8

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

app/jobs/solid_queue/recurring_job.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
class SolidQueue::RecurringJob < ActiveJob::Base
4+
queue_as :solid_queue_recurring
5+
6+
def perform(command)
7+
eval(command)
8+
end
9+
end

app/models/solid_queue/recurring_task.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ class RecurringTask < Record
77
serialize :arguments, coder: Arguments, default: []
88

99
validate :supported_schedule
10+
validate :ensure_command_or_class_present
1011
validate :existing_job_class
1112

1213
scope :static, -> { where(static: true) }
1314

15+
mattr_accessor :default_job_class
16+
self.default_job_class = RecurringJob
17+
1418
class << self
1519
def wrap(args)
1620
args.is_a?(self) ? args : from_configuration(args.first, **args.second)
@@ -20,6 +24,7 @@ def from_configuration(key, **options)
2024
new \
2125
key: key,
2226
class_name: options[:class],
27+
command: options[:command],
2328
arguments: options[:args],
2429
schedule: options[:schedule],
2530
queue_name: options[:queue].presence,
@@ -85,8 +90,14 @@ def supported_schedule
8590
end
8691
end
8792

93+
def ensure_command_or_class_present
94+
unless command.present? || class_name.present?
95+
errors.add :base, :command_and_class_blank, message: "either command or class_name must be present"
96+
end
97+
end
98+
8899
def existing_job_class
89-
unless job_class.present?
100+
if class_name.present? && job_class.nil?
90101
errors.add :class_name, :undefined, message: "doesn't correspond to an existing class"
91102
end
92103
end
@@ -113,7 +124,9 @@ def perform_later
113124
end
114125

115126
def arguments_with_kwargs
116-
if arguments.last.is_a?(Hash)
127+
if class_name.nil?
128+
command
129+
elsif arguments.last.is_a?(Hash)
117130
arguments[0...-1] + [ Hash.ruby2_keywords_hash(arguments.last) ]
118131
else
119132
arguments
@@ -126,7 +139,7 @@ def parsed_schedule
126139
end
127140

128141
def job_class
129-
@job_class ||= class_name&.safe_constantize
142+
@job_class ||= class_name.present? ? class_name.safe_constantize : self.class.default_job_class
130143
end
131144

132145
def enqueue_options

test/models/solid_queue/recurring_task_test.rb

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ def perform
122122
assert_not SolidQueue::RecurringTask.new(key: "task-id", class_name: "SolidQueue::RecurringTaskTest::JobWithoutArguments").valid?
123123
end
124124

125-
test "undefined job class" do
125+
test "valid and invalid job class and command" do
126+
# Command
127+
assert recurring_task_with(command: "puts '¡hola!'").valid?
128+
# Class
129+
assert recurring_task_with(class_name: "JobWithPriority").valid?
130+
131+
# Invalid class name
126132
assert_not recurring_task_with(class_name: "UnknownJob").valid?
127133

128-
# Empty class name
129-
assert_not SolidQueue::RecurringTask.new(key: "task-id", schedule: "every minute").valid?
134+
# Empty class name and command
135+
assert_not recurring_task_with(key: "task-id", schedule: "every minute").valid?
130136
end
131137

132138
test "task with custom queue and priority" do
@@ -154,6 +160,13 @@ def perform
154160
assert_equal 4, job.priority
155161
end
156162

163+
test "task configured with a command" do
164+
task = recurring_task_with(command: "JobBuffer.add('from_a_command')")
165+
enqueue_and_assert_performed_with_result(task, "from_a_command")
166+
167+
assert_equal "SolidQueue::RecurringJob", SolidQueue::Job.last.class_name
168+
end
169+
157170
private
158171
def enqueue_and_assert_performed_with_result(task, result)
159172
assert_difference [ -> { SolidQueue::Job.count }, -> { SolidQueue::ReadyExecution.count } ], +1 do
@@ -170,7 +183,13 @@ def enqueue_and_assert_performed_with_result(task, result)
170183
assert_equal result, JobBuffer.last_value
171184
end
172185

173-
def recurring_task_with(class_name:, **options)
174-
SolidQueue::RecurringTask.from_configuration("task-id", class: "SolidQueue::RecurringTaskTest::#{class_name}", **options.with_defaults(schedule: "every hour"))
186+
def recurring_task_with(class_name: nil, **options)
187+
options = options.dup.with_defaults(schedule: "every hour")
188+
189+
if class_name.present?
190+
options[:class] = "SolidQueue::RecurringTaskTest::#{class_name}"
191+
end
192+
193+
SolidQueue::RecurringTask.from_configuration("task-id", **options)
175194
end
176195
end

test/unit/scheduler_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class SchedulerTest < ActiveSupport::TestCase
1717
scheduler.stop
1818
end
1919

20-
test "run more than one instance of the dispatcher with recurring tasks" do
20+
test "run more than one instance of the scheduler with recurring tasks" do
2121
recurring_tasks = { example_task: { class: "AddToBufferJob", schedule: "every second", args: 42 } }
2222
schedulers = 2.times.collect do
2323
SolidQueue::Scheduler.new(recurring_tasks: recurring_tasks)

0 commit comments

Comments
 (0)