Search code examples
rubymultithreadingsidekiqidempotent

Basic Sidekiq Questions about Idempotency and functions


I'm using Sidekiq to perform some heavy processing in the background. I looked online but couldn't find the answers to the following questions. I am using:

Class.delay.use_method(listing_id) 

And then, inside the class, I have a

self.use_method(listing_id)
    listing = Listing.find_by_id listing_id
    UserMailer.send_mail(listing)
    Class.call_example_function()

Two questions:

  1. How do I make this function idempotent for the UserMailer sendmail? In other words, in case the delayed method runs twice, how do I make sure that it only sends the mail once? Would wrapping it in something like this work?

    mail_sent = false if !mail_sent UserMailer.send_mail(listing) mail_sent = true end

I'm guessing not since the function is tried again and then mail_sent is set to false for the second run through. So how do I make it so that UserMailer is only run once.

  1. Are functions called within the delayed async method also asynchronous? In other words, is Class.call_example_function() executed asynchronously (not part of the response / request cycle?) If not, should I use Class.delay.call_example_function()

Overall, just getting familiar with Sidekiq so any thoughts would be appreciated.

Thanks


Solution

  • Regarding idempotency, you can use https://github.com/mhenrixon/sidekiq-unique-jobs gem:

    All that is required is that you specifically set the sidekiq option for unique to true like below:

    sidekiq_options unique: true
    

    For jobs scheduled in the future it is possible to set for how long the job should be unique. The job will be unique for the number of seconds configured or until the job has been completed.

    *If you want the unique job to stick around even after it has been successfully processed then just set the unique_unlock_order to anything except :before_yield or :after_yield (unique_unlock_order = :never)

    I'm not sure I understand the second part of the question - when you delay a method call, the whole method call is deferred to the sidekiq process. If by 'response / request cycle' you mean that you are running a web server, and you call delay from there, so all the calls within the use_method are called from the sidekiq process, and hence outside of that cycle. They are called synchronously relative to each other though...