Priority is a decision, not a default
No job in this app calls queue_with_priority; a search of app/jobs/ for priority finds nothing. Every job still has a priority, because every row in solid_queue_jobs does: db/queue_schema.rb makes the column null: false. This lesson is about where that number comes from when nobody asked for one.
Two defaults, not one
ActiveJob::QueuePriority, mixed into every job:
module ActiveJob
module QueuePriority
module ClassMethods
mattr_accessor :default_priority
def queue_with_priority(priority = nil, &block)
if block_given?
self.priority = block
else
self.priority = priority
end
end
end
included do
class_attribute :priority, instance_accessor: false, default: default_priority
end
def priority
if @priority.is_a?(Proc)
@priority = instance_exec(&@priority)
end
@priority
end
end
end
default_priority is a plain mattr_accessor the app never sets, so it's nil. A job that never calls queue_with_priority returns nil from #priority: not 0, nil. Rails's own comment on the attribute, in active_job/core.rb, says what the number means once it exists: # Priority that the job will have (lower is more priority).
nil never reaches the database. Here's SolidQueue::Job.attributes_from_active_job:
def attributes_from_active_job(active_job)
{
queue_name: active_job.queue_name || DEFAULT_QUEUE_NAME,
active_job_id: active_job.job_id,
priority: active_job.priority || DEFAULT_PRIORITY,
scheduled_at: active_job.scheduled_at,
class_name: active_job.class.name,
arguments: active_job.serialize,
concurrency_key: active_job.concurrency_key
}
end
DEFAULT_PRIORITY = 0 is a constant on SolidQueue::Job. So there are two defaults, from two libraries. Rails's default is "no opinion", nil, and Solid Queue's is the floor it substitutes at the last possible moment, the INSERT. The mid-level course "Solid Queue: job architecture" showed what the stored number controls once it's in the table: order(priority: :asc, job_id: :asc), the sort every ready claim runs. This lesson stops one step earlier, at the decision the number stands for.
queue_with_priority, run
Here's a throwaway job, run with bin/rails runner against the development queue database, inside a transaction that was rolled back:
class PriorityProbeJob < ApplicationJob
self.queue_adapter = :solid_queue # development uses :async
queue_as :probe
queue_with_priority 20
def perform(*); end
end
j1 = PriorityProbeJob.perform_later
SolidQueue::Job.find_by(active_job_id: j1.job_id).priority
stored priority = 20
20, the number on the class. queue_with_priority sets the class's priority, ActiveJob::Core#initialize copies it into the instance as @priority = self.class.priority, and attributes_from_active_job writes it straight into the row.
What the app's jobs never decided
# app/jobs/partners/fetch_site_icon_job.rb
class Partners::FetchSiteIconJob < ApplicationJob
queue_as :default
# no queue_with_priority anywhere in this file
end
So Partners::FetchSiteIconJob#priority is nil, attributes_from_active_job substitutes DEFAULT_PRIORITY, and every row the job creates carries priority: 0. Nobody decided 0 was right for it; nobody decided anything, and 0 is where the chain bottoms out. The same holds for every other job in the app. That's a fact about the app, not a criticism: the jobs that share a queue have never needed ordering among themselves. The rest of the course is about what changes when they do.
Key takeaways
ActiveJob::QueuePriority#priorityisniluntil a job callsqueue_with_priority: Rails's default is no opinion, not0.SolidQueue::Job.attributes_from_active_jobsubstitutesDEFAULT_PRIORITY = 0only when it builds the row, withactive_job.priority || DEFAULT_PRIORITY. That floor is Solid Queue's, not Rails's.queue_with_priority 20lands insolid_queue_jobs.priorityunchanged:20in,20stored.- No job in the app calls
queue_with_priority, so all of them get priority0by default, not by design.
Keep going with lesson 2
Static vs dynamic priority, and who wins
Compares static and block-based queue_with_priority with .set(priority:), which overrides the class value when present.
A free account also gives you the quizzes, your progress and notes, and the discussion.