Reputation: 20171
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
Upvotes: 4
Views: 1328
Reputation: 20171
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...
Upvotes: 3
Reputation: 1
If you are using Delayed Job as the implementation for Active Job then take a look at the 'activejob-trackable' gem. https://github.com/ignatiusreza/activejob-trackable
It uses another table that tracks the jobs and can throttle and debounce.
Upvotes: 0
Reputation: 418
What I would do is schedule a periodic task, lets say every 5 minutes that checks if there is someone who has to be notified. Yes it seems an expensive operation, but for your use case I don't see (for now) others solutions. So lets say you have 10 users that uses a chat. Every 5 minutes you could check if there are users that didn't see some messages, and if so you notify them only if they are inactive from N minutes.
To schedule such task you could use crono gem. Check this answer.
Crono lets you do thing like that:
Crono.perform(CheckUsersToBeNotifiedJob).every 5.minutes
Upvotes: 0