Rails How to Tell If a Sidekiq Worker Is Done with Perform_Async

Rails how to tell if a sidekiq worker is done with perform_async

Checkout the following extension gem to sidekiq: https://github.com/utgarda/sidekiq-status/blob/master/README.md

This is from the read me:

job_id = MyJob.perform_async(*args)
data = Sidekiq::Status::get_all job_id
data # => {status: 'complete', update_time: 1360006573, vino: 'veritas'}
Sidekiq::Status::get job_id, :vino #=> 'veritas'
Sidekiq::Status::at job_id #=> 5
Sidekiq::Status::total job_id #=> 100
Sidekiq::Status::message job_id #=> "Almost done"

What happends when a perform_async is called but sidekiq is not running?

Simple answer: it is not done. It will be done later

As the name it self is saying it puts it in a que. When you turn on sidekiq it will read all data from que and execute all tasks.

But for this to work you need to have Redis working. Redis is responsible for saving data in a que, it is a kind of memory. Without Redis you would get an error.

What is perform_async in sidekiq

perform_async - a method that push your job with your params in the async queue (create a record in your async backend, Redis by default), to allow Sidekiq catch and perform it on the order of queue

Source: https://github.com/mperham/sidekiq/blob/e2f92e8279d1947aa45eb86acc73f9ebe7a92c9c/lib/sidekiq/worker.rb#L6-L43

Sidekiq: perform_async and order-dependent operations

If the email can only be sent after the text message has been sent, then send the email after successful completion of sending the text.

class ContactUserWorker
include Sidekiq::Worker

def perform(user_id)
SendUserTextWorker.perform_async(user_id)
end
end

class SendUserTextWorker
include Sidekiq::Worker

def perform(user_id)
user = User.find(user_id)
text_sent = user.send_text
SendUserEmailWorker.perform_async(user_id) if text_sent
end
end

class SendUserEmailWorker
include Sidekiq::Worker

def perform(user_id)
user = User.find(user_id)
user.send_email
end
end

In user.send_text you need to handle the fact that neither the text or the email has been sent.

perform_async not working in sidekiq

Well I found your bug, in your boot.rb file you have this line:

require 'sidekiq/testing/inline' if RACK_ENV == 'development'

This bit of code, uses Sidekiq's Testing framework which bypasses redis and runs it almost as if it's a ruby class (ie it doesn't ever get queued on redis). Remove that line and only use it in your test suite (if you need it).

You'll also need to remove that pid file from your YML file, you don't need that and if you do, it's probably only for production. My 2cents - remove it.

Once you do that, you're good to go:

Here's your rackup with a get request to /hardworker:

[2015-06-07 07:54:25] INFO  WEBrick 1.3.1
[2015-06-07 07:54:25] INFO ruby 2.2.2 (2015-04-13) [x86_64-darwin14]
[2015-06-07 07:54:25] INFO WEBrick::HTTPServer#start: pid=74128 port=9292
INFO - I'll call HardWorker
INFO - HardWorker was called
DEBUG - GET (0.0131s) /hardworker - 200 OK
::1 - - [07/Jun/2015:07:55:32 -0400] "GET /hardworker HTTP/1.1" 200 46 0.0291

Here's sidekiq processing that job in the background:

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
ss
sss sss ss
s sss s ssss sss ____ _ _ _ _
s sssss ssss / ___|(_) __| | ___| | _(_) __ _
s sss \___ \| |/ _` |/ _ \ |/ / |/ _` |
s sssss s ___) | | (_| | __/ <| | (_| |
ss s s |____/|_|\__,_|\___|_|\_\_|\__, |
s s s |_|
s s
sss
sss

INFO - Running in ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
INFO - See LICENSE and the LGPL-3.0 for licensing details.
INFO - Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org/pro
INFO - Starting processing, hit Ctrl-C to stop
DEBUG -
INFO -
INFO - Doing hard work
INFO - redis location: [127.0.0.1:6379]
INFO - connected clients: [3]
INFO - hard work was done
INFO -

Rails 6 grab results from Sidekiq Job - is it possible?

I don't believe what you want is possible.

https://github.com/mperham/sidekiq/issues/3532

The return value will be GC'd like any other unused data in a Ruby process. Jobs do not have a "result" in Sidekiq and Sidekiq does nothing with the value.

You would need some sort of model instead that keeps track of your background tasks. This is off the cuff but should give you an idea.

EG

# @attr result [Array]
# @attr status [String] Values of 'Pending', 'Error', 'Complete', etc..
class BackgroundTask < ActiveRecord
attr_accessor :product_codes
after_create :enqueue

def enqueue
::Imports::SyncProductsWorker.perform_async(product_codes, self.id)
end
end

def perform(list, id)
response = ::Imports::SynchronizeProducts.new(list).call
if (response.has_errors?)
BackgroundTask.find(id).update(status: 'Error', result: response)
else
BackgroundTask.find(id).update(status: 'Complete', result: response)
end
end

Then just use the BackgroundTask model for your frontend display.

Test Sidekiq job that changes value of object

To test that your worker is doing the work you intend it to do - test perform rather than perform_async:

describe OrderProcessorWorker do

it 'changes order status' do
subject.perform(order_id)

expect(Order.find(id: order_id).status).to eq 'processed'
end
end


Related Topics



Leave a reply



Submit