FEATURE: push post rebake regular task to low priority queue

FEATURE: push post rebake regular task to low priority queue

This allows us to run regular rebakes without starving the normal queue.

It additionally adds the ability to specify queue with Jobs.enqueue so we can specifically queue a job with lower priority using the queue arg.

diff --git a/app/jobs/base.rb b/app/jobs/base.rb
index 0bd5b6f..a7d2399 100644
--- a/app/jobs/base.rb
+++ b/app/jobs/base.rb
@@ -197,14 +197,28 @@ module Jobs
 
     # If we are able to queue a job, do it
     if SiteSetting.queue_jobs?
-      if opts[:delay_for].present?
-        klass.perform_in(opts.delete(:delay_for), opts)
-      else
-        Sidekiq::Client.enqueue(klass, opts)
+      hash = {
+        'class' => klass,
+        'args' => [opts]
+      }
+
+      if delay = opts.delete(:delay_for)
+        if delay.to_f > 0
+          hash['at'] = Time.now.to_f + delay.to_f
+        end
+      end
+
+      if queue = opts.delete(:queue)
+        hash['queue'] = queue
       end
+
+      klass.client_push(hash)
+
     else
       # Otherwise execute the job right away
       opts.delete(:delay_for)
+      opts.delete(:queue)
+
       opts[:sync_exec] = true
       if Rails.env == "development"
         Scheduler::Defer.later("job") do
diff --git a/app/jobs/scheduled/periodical_updates.rb b/app/jobs/scheduled/periodical_updates.rb
index 2ab9517..5701e6d 100644
--- a/app/jobs/scheduled/periodical_updates.rb
+++ b/app/jobs/scheduled/periodical_updates.rb
@@ -15,7 +15,7 @@ module Jobs
       (@call_count % 24) == 1
     end
 
-    def execute(args)
+    def execute(args = nil)
       # Feature topics in categories
       CategoryFeaturedTopic.feature_topics(batched: true)
 
@@ -29,7 +29,7 @@ module Jobs
 
       # Forces rebake of old posts where needed, as long as no system avatars need updating
       if !SiteSetting.automatically_download_gravatars || !UserAvatar.where("last_gravatar_download_attempt IS NULL").limit(1).first
-        problems = Post.rebake_old(SiteSetting.rebake_old_posts_count)
+        problems = Post.rebake_old(SiteSetting.rebake_old_posts_count, priority: :low)
         problems.each do |hash|
           post_id = hash[:post].id
           Discourse.handle_job_exception(hash[:ex], error_context(args, "Rebaking post id #{post_id}", post_id: post_id))
diff --git a/app/models/post.rb b/app/models/post.rb
index ff6c328..19d093d 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -515,7 +515,7 @@ class Post < ActiveRecord::Base
     PostRevisor.new(self).revise!(updated_by, changes, opts)
   end
 
-  def self.rebake_old(limit)
+  def self.rebake_old(limit, priority: :normal)
 
     limiter = RateLimiter.new(
       nil,
@@ -534,7 +534,7 @@ class Post < ActiveRecord::Base
         break if !limiter.can_perform?
 
         post = Post.find(id)
-        post.rebake!
+        post.rebake!(priority: priority)
 
         begin
           limiter.performed!
@@ -560,15 +560,13 @@ class Post < ActiveRecord::Base
     problems
   end
 
-  def rebake!(opts = nil)
-    opts ||= {}
-
-    new_cooked = cook(raw, topic_id: topic_id, invalidate_oneboxes: opts.fetch(:invalidate_oneboxes, false))
+  def rebake!(invalidate_broken_images: false, invalidate_oneboxes: false, priority: nil)
+    new_cooked = cook(raw, topic_id: topic_id, invalidate_oneboxes: invalidate_oneboxes)
     old_cooked = cooked
 
     update_columns(cooked: new_cooked, baked_at: Time.new, baked_version: BAKED_VERSION)
 
-    if opts.fetch(:invalidate_broken_images, false)
+    if invalidate_broken_images
       custom_fields.delete(BROKEN_IMAGES)
       save_custom_fields
     end
@@ -578,7 +576,7 @@ class Post < ActiveRecord::Base
     QuotedPost.extract_from(self)
 
     # make sure we trigger the post process
-    trigger_post_process(bypass_bump: true)
+    trigger_post_process(bypass_bump: true, priority: priority)
 
     publish_change_to_clients!(:rebaked)
 
@@ -692,7 +690,7 @@ class Post < ActiveRecord::Base
   end
 
   # Enqueue post processing for this post
-  def trigger_post_process(bypass_bump: false)
+  def trigger_post_process(bypass_bump: false, priority: :normal)
     args = {
       post_id: id,
       bypass_bump: bypass_bump,
@@ -700,6 +698,11 @@ class Post < ActiveRecord::Base
     args[:image_sizes] = image_sizes if image_sizes.present?
     args[:invalidate_oneboxes] = true if invalidate_oneboxes.present?
     args[:cooking_options] = self.cooking_options
+
+    if priority == :low
+      args[:queue] = 'low'
+    end
+
     Jobs.enqueue(:process_post, args)
     DiscourseEvent.trigger(:after_trigger_post_process, self)
   end
diff --git a/spec/jobs/periodical_updates_spec.rb b/spec/jobs/periodical_updates_spec.rb
index b2ba6c6..8b0e88b 100644
--- a/spec/jobs/periodical_updates_spec.rb
+++ b/spec/jobs/periodical_updates_spec.rb
@@ -13,13 +13,24 @@ describe Jobs::PeriodicalUpdates do
     SiteSetting.automatically_download_gravatars = false
     post = create_post
     post.update_columns(baked_at: Time.new(2000, 1, 1), baked_version: -1)
-    described_class.new.execute({})
+
+    Sidekiq::Testing.fake! do
+      Jobs::ProcessPost.jobs.clear
+
+      Jobs::PeriodicalUpdates.new.execute
+
+      jobs = Jobs::ProcessPost.jobs
+      expect(jobs.length).to eq(1)
+
+      expect(jobs[0]["queue"]).to eq("low")
+    end
 
     post.reload
     expect(post.baked_at).to be > 1.day.ago
-
     baked = post.baked_at
-    described_class.new.execute({})
+
+    # does not rebake
+    Jobs::PeriodicalUpdates.new.execute
     post.reload
     expect(post.baked_at).to eq(baked)
   end

GitHub sha: e08a3f71

3 Likes