Sidekiq run job only once - ruby-on-rails

I have a question about how can you run sidekiq job only once f.e. just on the start of rails web-app. One thing I tried is to initialize redis semaphore in the config/initializer.rb and then used it in job, but it kinda didn't work. Here's the code I'm trying to get working:
config/initializer.rb
SEMAPHORE = Redis::Semaphore.new(:semaphore_name, :host => "localhost")
queue_worker.rb
class QueueWorker
include Sidekiq::Worker
def perform
logger.info 'Start polling'
unless SEMAPHORE.locked?
logger.info 'Im here only once'
SEMAPHORE.lock
end
end
end
root_controller_action
QueueWorker.perform_async
Well another variant I don't know if it's possible to run sidekiq job in the initializer. If you can do that, there's no need in semaphore at all.
Thx for answering.

Related

Rails 6 how to check if sidekiq job is running

In my Rails 6 API only app I've got FetchAllProductsWorker background job which takes around 1h30m.
module Imports
class FetchAllProductsWorker
include Sidekiq::Worker
sidekiq_options queue: 'imports_fetch_all'
def perform
# do some things
end
end
end
During this time the frontend app sends requests to the endpoint on BE which checks if the job is still running. I need to send true/false of that process. According to the docs there is a scan method - https://github.com/mperham/sidekiq/wiki/API#scan but none of these works for me even when worker is up and running:
# endpoint method to check sidekiq status
def status
ss = Sidekiq::ScheduledSet.new
render json: ss.scan('FetchAllProductsWorker') { |job| job.present? }
end
The console shows me:
> ss.scan("\"class\":\"FetchAllProductsWorker\"") {|job| job }
=> nil
> ss.scan("FetchAllProductsWorker") { |job| job }
=> nil
How to check if particular sidekiq process is not finished?
Maybe this will be useful for someone. Sidekiq provides programmatic access to the current active worker using Sidekiq::Workers https://github.com/mperham/sidekiq/wiki/API#workers
So based on that we could do something like:
active_workers = Sidekiq::Workers.new.map do |_process_id, _thread_id, work|
work
end
active_workers.select do |worker|
worker['queue'] == 'imports_fetch_all'
end.present?

How do you call a (daily) sidekiq scheduled worker without calling the worker?

Something simple, I'm sure but I've been searching and can't find an answer.
in brief: I want to set up a daily mailer to email a lists of tasks daily.
I have a worker (scheduled every minute, and only puts'ing for dev):
class DailyReminderWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence do
hourly.minute_of_hour(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59)
end
def perform
User.find_each do |user|
#user = user.name
puts "user name is #{#user}"
#reminder = Remindarrr.where(user_id: user.id)
#reminder.each do |r|
puts r.title
end
end
end
end
I know I can call this with the following in a controller:
DailyReminderWorker.perform_async
This works and outputs every minute but every time the page refreshes it also fires. (less useful for a daily mailer.)
How do you call the worker to queue the job without it firing immediately?
Where would you put the perform.async?
Thanks a lot!
If you are on a Linux platform, just use cron. very easy to setup.

How to create a background job for get request with Sidekiq and httparty?

I need help developing a worker with sidekiq for this situation:
I have a helper that looks like this:
module UploadsHelper
def save_image
response = HTTParty.get(ENV['IMAGE_URI'])
image_data = JSON.parse(response.body)
images = image_data["rows"].map do |line|
u = Image.new
u.description = line[5]
u.image_url = line[6]
u.save
u
end
images.select(&:persisted?)
end
end
In my app/views/uploads/index.html.erb I just do this
<% save_image %>
Now, when a user visits the uploads/index page the images are saved to the database.
The problem is that the get request to the API is really slow. I want to prevent request timeouts by moving this to a background job with sidekiq.
This is my workers/api_worker.rb
class ApiWorker
include Sidekiq::Worker
def perform
end
end
I just don't know the best way to proceed from here.
Performing this task using a Sidekiq worker implies that the task will run in async, and thus, it will not be able to return the response immediately, which is being sent by images.select(&:persisted?).
First of all, instead of calling save_image, you need to call the worker's perform_async method.
<% ApiWorker.perform_async %>
This will enqueue a job in Sidekiq's queue (your_queue in this example). Then in worker's perform method, call the save_image method of UploadsHelper.
class ApiWorker
include Sidekiq::Worker
sidekiq_options queue: 'your_queue'
include UploadsHelper
def perform
save_image
end
end
You may want to save the response of save_image somewhere. To get Sidekiq start processing the jobs, you can run bundle exec sidekiq from your app directory.

Restarting sidekiq jobs on reboot

Currently I'm restarting my sidekiq jobs using a cron job that triggers the method below
class RestartSidekiqJobs
require 'sidekiq/api'
class << self
def restart_jobs
Sidekiq::ScheduledSet.new.clear
channels = Channel.all
channels.each do |channel|
FetchMoreDataJob.perform_later(channel: channel)
end
end
end
end
I'm not convinced however that this is the best way to handle this so I figured I'd see if there were better solutions out there.

perform not being called for Delayed Jobs

I'm using delayed_job 2.1.4 from collectiveidea, and it seems the perform method is never called even though the jobs are processed and removed from the queue. Am I missing something?
I'm using Rails 3.0.5 on Heroku
In the Controller:
Delayed::Job.enqueue FacebookJob.new
In the Job class:
class FacebookJob
def initialize
end
def perform
fb_auths = Authentication.where(:provider => 'facebook')
fb_auths.each do |auth|
checkins = FbGraph::User.new('me', :access_token => URI.encode(auth.token)).checkins
if checkins != nil
checkins.each do |checkin|
[...]
end
end
end
end
end
(the whole code: https://gist.github.com/966509)
The simple answer: does DelayedJob know about the Authentication and FBGraph::User classes? If not, you'll see exactly the behavior you describe: the items will be silently removed from the queue.
See this entry in the Delayed Job Wiki in the Delayed Job Wiki.
Try adding 'require authentication' and 'require fb_graph' (or whatever) in your facebook_job.rb file.

Resources