Search code examples
ruby-on-railssidekiqdelayed-job

Rails debounce delayed job background task? removing duplicates


Debouncing is a common method to postpone a function/job from executing until after certain time has passed.

Use-case: A conversation with active chatting from multiple users, they should not receive an email notification for each message typed. But more than likely after a few minutes of silence, if the messages are unread, the user should see a notification.

Delayed_Job

Has no solution, has related issues: https://github.com/collectiveidea/delayed_job/issues/72

Sidekiq

https://github.com/hummingbird-me/sidekiq-debounce


Solution

  • Doing yourself is not so bad.

    class AdminJob
      def self.debounce(job, args={})
        handler = YAML.dump(job)
        count = Delayed::Job.where(handler: handler).where('locked_at IS NULL').delete_all
        Rails.logger.info("deleted: #{count} jobs")
        Delayed::Job.enqueue(job, args)
      end
    end
    

    Instead of writing:

    Delayed::Job.enqueue(YourJobName.new(account_id), {run_at: 10.minutes.from_now})
    

    You now write:

    AdminJob.debounce(YourJobName.new(account_id), {run_at: 10.minutes.from_now})
    

    Delayed job serializes your job params in YAML and then saves it to the database as handler. So if you call AdminJob.debounce(...) 10 times in a row, it will delete before each.

    Make sure to give yourself time (5.minutes, etc) to give users to keep taking actions. If you run your job after 1 second, its likely they'll keep taking actions and trigger again.

    Yes i'm answering my own question 3 years later...