I have a Rails app that uses Rufus Scheduler combined with Delayed jobs to execute background jobs. There are another jobs, but the one I'm having trouble with is scheduled in a controller using this code:
def create
#harvest_plan = HarvestPlan.new(resource_params)
#harvest_plan.start_date = Time.parse(resource_params[:start_date])
if #harvest_plan.save
ApplicationController.new.insert_in_messages_list(session, :success, 'Harvest plan created')
schedule_harvest
redirect_to farms_path
end
end
private
def schedule_harvest
Rufus::Scheduler.singleton.every "#{#harvest_plan.hours_between}h",
:times => #harvest_plan.repetitions, :first_at => #harvest_plan.start_date do
CreateHarvestFromPlanJob.perform_later
end
end
The job is supposed to be scheduled according to the harvest plan model, which indicates how many hours must past between jobs, when is the first one supposed to be scheduled and how many repetitions must occur. Everything works perfect except for the first job, which does happen at the time specified with first_at but it is scheduled twice for some reason, delayed jobs then executes the job twice. I tried using the mutex, blocking and overlap options, but it did nothing different. After the first job (scheduled twice) everything works fine. The next jobs are scheduled on time and just once. I have just one delayed jobs worker
Why is this happening?
I am running Rails 4.2.4, Ruby 2.2.2 and Rufus 3.3.2. Since the error happens both with passenger and webrick I assume this has nothing to do with the problem.
Why is Rufus scheduling the first job twice?
because of a bug you found: https://github.com/jmettraux/rufus-scheduler/issues/231
Thanks a lot!
Related
We have an issue similar to this Sidekiq schedule same worker to queue when done
The crux of the issue is that if more then one argument is passed to the perform_in it does not schedule them for later, but processes them as usual.
This works as expected, but is not useful because there are no arguments
being passed into the new job
def perform(id, mode)
begin
Some::Process.remediate(App.find(id), mode)
rescue CustomErrors::MyError => e
# This will schedule a job, but without arguments :(
self.class.perform_in(2.hours)
end
end
This would be useful, but does not work as expected
The job completes and nothing is rescheduled
def perform(id, mode)
begin
Some::Process.remediate(App.find(id), mode)
rescue CustomErrors::MyError => e
# This does not schedule a job
self.class.perform_in(2.hours, id, mode)
end
end
Used:
Sidekiq 3.5.1
Rails 4.2.4
ruby 2.3.1p112
dev environment
Any help is highly appreciated
UPDATE
When the code is ran with a binding
binding.pry
self.class.perform_in(2.hours, 2, 12345)
It does schedule a job, but only on the first time. When it comes to it the second time around the job is being run for some reason.
In my current project I am doing some process in background by using Delayed Job gem. It's working fine in local but in production jobs are inserted into Delayed Job table but DJ not picking few jobs from that DJ table. Could any one have idea how Delayed Job will pick up jobs from Delayed Job table.
Below is the Delayed job code in my project:
Delayed::Job.enqueue(ProposalJob.new(current_user, #proposal, request.host, params[:proposal][:revision_notes], params[:proposal][:close_date]), :queue => 'publishing')
Delayed job configuration in my project:
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.max_attempts = 3
Delayed::Worker.max_run_time = 1.hours
Delayed::Worker.read_ahead = 10
It's not possible that delayed job will pick some job and not pick other.
Either it will process all job or not process any. If it process any job then your configuration is right.
There might be issue due to Delayed::Worker.destroy_failed_jobs = false this configuration. if your any job fails three times then it will not get deleted from your delayed job table. Because of due to this you might feel that this jobs not get processed.
Try debug your delayed job code with puts.
You can also try https://github.com/resque/resque-scheduler this will provide visual way to watch delayed jobs.
I'm using rufus-scheduler to schedule jobs at a certain date through the following code:
job = Rufus::Scheduler.singleton.schedule_at #post.read_attribute(:parse_time).to_s do
end
I then save the id of that job in my post class
#post.update_attribute(:job_id, job.id)
However, if I try and access that job again by calling:
Rufus::Scheduler.singleton.job(#post.read_attribute(:job_id)).unschedule
I get an error because the job is nil. If I try and look at the jobs of the Scheduler by calling:
Rufus::Scheduler.singleton.jobs
I get a blank array. Can anyone explain why my jobs aren't saving properly kept / being tracked?
Here's my initialization file for the scheduler. Do I have to do anything to enable singleton though? Or does it come with rails automatically:
require 'rufus-scheduler'
# Create singleton rufus scheduler
s = Rufus::Scheduler.singleton
rufus-scheduler doesn't keep triggered jobs around.
Your job has probably triggered and is gone.
We have a model that generates reports.
Each report can be very complicated and may take a long time to load. Therefore, we are using delayed_job to do this in background.
Everything works on my local computer but in our production environment jobs randomly disappear. They do not even exist in the delayed_job.log as success or failed. Delayed jobs are created but sometimes they are deleted without throwing any errors or doing the work.
This is the method in our model:
def generate_html
ac = DelayedJobsController.new()
tmp_html = ac.render_to_string partial: self.partial_path, object: self
self.update_attributes(html: tmp_html, done: true)
end
handle_asynchronously :generate_html
After lots of work we found the problem.
When we did run crontab -l and ps aux we cud see that two instances of delayed_job was running. After we killed the oldest one of them all worked like it should.
I am facing a very interesting problem. I have tested the Delay job gem 4 times. I doubt it is the design problem of the gem or a bug. I use command rake jobs:work to create worker to do delayed job.
Once I create a LongTask record, i also make a delayed job which will change the attributeminutes_delayed to 2.
The gem works perfectly if I don't update the attributes. But once I edited the description, the gem will not work properly, which means it will not execute the delayed job, but the related delayed job record will be removed in the database.
Interesting final result:
It Seems to reference a object with attribute that is exactly the same, this picture was captured before the running time have gone over.
This one was captured after all tests have been gone though. You can see the delayed job record for test4 have been removed even this delayed job did't have any effect.
terminal results (only 2 jobs are executed)
[Worker(host:Jasonteki-MacBook-Air.local pid:1726)] Starting job worker
[Worker(host:Jasonteki-MacBook-Air.local pid:1726)] LongTask#set_delay_time_without_delay completed after 0.0343
[Worker(host:Jasonteki-MacBook-Air.local pid:1726)] 1 jobs processed at 16.6270 j/s, 0 failed ...
[Worker(host:Jasonteki-MacBook-Air.local pid:1726)] LongTask#set_delay_time_without_delay completed after 0.0105
[Worker(host:Jasonteki-MacBook-Air.local pid:1726)] 1 jobs processed at 51.4774 j/s, 0 failed ...
Code in model:
def set_delay_time(time)
self.minutes_delayed = time
# very important for this, otherwise cannot write the change into the database
self.save
end
handle_asynchronously :set_delay_time, :run_at => Proc.new { 2.minutes.from_now }
Code in controller:
def create
#long_task = LongTask.new(params[:long_task])
respond_to do |format|
if #long_task.save
#long_task.set_delay_time(2)
Without seeing your code, it's impossible to tell for sure, but it's likely that both of your delayed jobs are working on serialized copies of your object, rather than reloading them from the database.