I have a worker like this:
class Worker
include Sidekiq::Worker
def perform
# ...
end
end
But there's something error with this worker, so I want to clear all jobs of it but don't want to clear jobs of other workers.
How can I implement this? Thanks.
Use the API to find and delete the jobs.
https://github.com/mperham/sidekiq/wiki/API#queue
Related
I encountered an issue with sidekiq: I want to set timeout for jobs, meaning when a job has process time greater than timeout then that job will stop.
I have searched how to set global timeout config in file sidekiq.yml. But I want to set separate timeout for difference separate jobs meaning one of classes to define worker will have particular timeout config.
Can you help me. Thanks so much.
There's no approved way to do this. You cannot stop a thread safely while it is executing. You need to change your job to check periodically if it should stop.
You can set network timeouts on any 3rd party calls you are making so that they time out.
You can wrap your job code inside a timeout block like the below:
Timeout::timeout(2.hours) do
***. do possibly long-running task *****
end
The job will fail automatically after 2 hours.
This is the same method as yassen suggested, but more concrete.
class MyCustomWorker
include Sidekiq::Worker
def perform
begin
Timeout::timeout(30.minutes) do # set timeout to 30 minutes
perform_job()
end
rescue Timeout::Error
Rails.logger.error "timeout reached for worker"
end
end
def perform_job
# worker logic here
end
end
I have some methods that works with API of third party app. To do it on button click is no problem, but it should be permanent process.
How to run them background? And how to pause the cycle for make some other works with same API and resume the cycle after the job is done.
Now I read about ActiveJob, but its has time dependences only...
UPDATE
I've tried to make it with whenever and sidekiq, task runs, but it do nothing. Where to look for logs I can't understand.
**schedule.rb**
every 1.minute do
runner "UpdateWorker.perform_async"
end
**update_worker.rb**
class UpdateWorker
include Sidekiq::Worker
include CommonMods
def perform
logger.info "Things are happening."
logger.debug "Here's some info: #{hash.inspect}"
myMethod
end
def myMethod
....
....
....
end
end
It's not exactly what I need, but better then nothing. Can somebody explain me with examples?
UPDATE 2 After manipulating with code it's absolutely necessary to restart sidekiq . With this problem is solved, but I'm not sure that this is the best way.
You can define a job which enqueues itself:
class MyJob < ActiveJob::Base
def perform(*args)
# Do something unless some flag is raised
ensure
self.class.set(wait: 1.hour).perform_later(*args)
end
end
There are several libraries to schedule jobs on a regular basis. For example you could use to sidekiq-cron to run a job every minute.
If you want to pause it for some time, you could set a flag somewhere (Redis/database/file) and skip execution as long it is detected.
On a somewhat related note: don't use sidetiq. It was really great but it's not maintained anymore and has incompatibilities to current Sidekiq versions.
Just enqueue next execution in ensure section after job completes after checking some flag that indicates that it should.
Also i recommend adding some delay there so that you don't end up with dead loop on some error inside job
I dont know ActiveJobs, but I can recommend the whenever gem to create cron (periodic background) jobs. Basically you end up writing a rake tasks. Like this:
desc 'send digest email'
task send_digest_email: :environment do
# ... set options if any
UserMailer.digest_email_update(options).deliver!
end
I never added a rake task to itself but for repeated processing you could do somehow like this (from answers to this specific question)
Rake::Task["send_digest_email"].execute
I found this Schedule one-time jobs in Rails
but this only shows how schedule one-time. I am interested in scheduling a recurring job.
Delayed_job has this
self.delay(:run_at => 1.minute.from_now)
How do I do something like that in Rails 4.2/Active Job?
Similar to rab3's answer, since ActiveJob has support for callbacks, I was thinking of doing something like
class MyJob < ActiveJob::Base
after_perform do |job|
# invoke another job at your time of choice
self.class.set(:wait => 10.minutes).perform_later(job.arguments.first)
end
def perform(the_argument)
# do your thing
end
end
activejob callbacks
If you want to delay the job execution to 10 minutes later, two options:
SomeJob.set(wait: 10.minutes).perform_later(record)
SomeJob.new(record).enqueue(wait: 10.minutes)
Delay to a specific moment from now use wait_until.
SomeJob.set(wait_until: Date.tomorrow.noon).perform_later(record)
SomeJob.new(record).enqueue(wait_until: Date.tomorrow.noon)
Details please refer to http://api.rubyonrails.org/classes/ActiveJob/Base.html.
For recurring jobs, you just put SomeJob.perform_now(record) in a cronjob (whenever).
If you use Heroku, just put SomeJob.perform_now(record) in a scheduled rake task. Please read more about scheduled rake task here: Heroku scheduler.
You can just re-enqueue the job at the end of the execution
class MyJob < ActiveJob::Base
RUN_EVERY = 1.hour
def perform
# do your thing
self.class.perform_later(wait: RUN_EVERY)
end
end
If you're using resque as your ActiveJob backend, you can use a combination of resque-scheduler's Scheduled Jobs and active_scheduler (https://github.com/JustinAiken/active_scheduler, which wraps the scheduled jobs to work properly with ActiveJob).
I'm using Sidetiq and Sidekiq together to recurring jobs :
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { secondly(3) }
def perform(id,last_occurrence)
# magic happens
end
However, now I want to stop the entire enqueuing process. I want to remove all the process from Sidetiq. How can I do?
Kind of late on this it looks like, but here we go anywho.
You can delete all scheduled sidetiq process like this:
Sidetiq::scheduled.each { |occurrence| occurrence.delete }
As far as preventing sidetiq from queuing additional jobs, i'm not sure how that works or how to dynamically stop it.
I have a Sidekiq worker in my application that essentially works like this:
class SetResultsWorker
include Sidekiq::Worker
def perform
ResultSetter.new.set_results!
end
end
class ResultSetter
def set_results!
events = Event.started.without_results
do_something if events.any?
end
end
The problem is that this events.any? is returning falsewhen it should not. It's not a problem with the scopes because when executing the worker synchronously (SetResultsWorker.new.perform), everything works OK. Any ideas?
EDIT: More information. This worker is executed periodically by a daemon. The first executions are OK, but then it stops working.