Has anyone been able to get scheduled jobs to work in Rails 4.2?
I am using resque, and I am attempting to use resque-scheduler to schedule jobs. I have a schedule that get loaded and the scheduler runs, and even looks like it is running the jobs but it doesn't do anything.
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Starting
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Loading Schedule
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Scheduling friends
resque-scheduler: [INFO] 2014-09-16T01:54:25-07:00: Schedules Loaded
resque-scheduler: [INFO] 2014-09-16T01:54:55-07:00: queueing FriendsJob (friends)
I can enqueue jobs like this and they get processed.
TestJob.enqueue(params[:id])
and I get this output in the worker log
got: (Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])
** [01:24:01 2014-09-16] 54841: resque-1.25.2: Processing default since 1410855841 [ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper]
** [01:24:01 2014-09-16] 54841: Running before_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]
** [01:24:01 2014-09-16] 54841: resque-1.25.2: Forked 54882 at 1410855841
** [01:24:01 2014-09-16] 54882: Running after_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]
Hello World!!
** [01:24:01 2014-09-16] 54882: done: (Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])
But when I try to schedule a job, it looks like the are getting enqueue but they well not doing anything.
Here is the schedule.yml
friends:
every: "30s"
queue: "friends"
class: "FriendsJob"
args: 8
description: "Friends jobs scheduler"
Here is the output from the scheduled job.
** [01:23:36 2014-09-16] 54841: got: (Job{friends} | FriendsJob | [8])
** [01:23:36 2014-09-16] 54841: resque-1.25.2: Processing friends since 1410855816 [FriendsJob]
** [01:23:36 2014-09-16] 54841: Running before_fork hooks with [(Job{friends} | FriendsJob | [8])]
** [01:23:36 2014-09-16] 54841: resque-1.25.2: Forked 54880 at 1410855816
** [01:23:36 2014-09-16] 54880: Running after_fork hooks with [(Job{friends} | FriendsJob | [8])]
** [01:23:36 2014-09-16] 54880: done: (Job{friends} | FriendsJob | [8])
After reading this http://dev.mikamai.com/post/96343027199/rails-4-2-new-gems-active-job-and-global-id I am suspecting it has something to do with ActiveJob and GlobalId.
Take a look at the difference enqueued
** [01:24:01 2014-09-16] 54841: Running before_fork hooks with [(Job{default} | ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper | ["TestJob", "98732ce5-17f7-4da3-9a03-a5d2f8f74e84", "8"])]
vs scheduled
** [01:23:36 2014-09-16] 54841: Running before_fork hooks with [(Job{friends} | FriendsJob | [8])]
The jobs themselves were generated via
rails g job <JobName>
They look like this:
class TestJob < ActiveJob::Base
queue_as :default
def perform(friend_id)
friend = Friend.find(friend_id)
name = friend.name.swapcase
puts "Hello World!!"
end
end
class FriendsJob < ActiveJob::Base
queue_as :friends
def perform(friend_id)
friend = Friend.find(friend_id)
name = friend.name.swapcase
puts "Hello World!!"
end
end
Any help with this will be greatly appreciated and thanks in advance.
********* UPDATE *********
I've removed the action_job railtie and I am using Resque and Resque-Scheduler only, and scheduled jobs are working now. So this does seems to be related to ActionJob/GlobalId. I've open an issue in the rails project. Hopefully, they will fix it soon.
****** SECOND UPDATE ********* I got an update on this. Cristianbica who works in the ActiveJob codebase said this. "We haven't thought at recurring jobs so far and we don't support this as none of the adapters support this without an external gem. However this is a very nice feature but I don't think we can make it in time for 4.2. Also I'm not sure it will suitable to be included in rails"
https://github.com/JustinAiken/active_scheduler is a gem that wraps the one into the other
UPDATE: 4/4/16 - Whilst the below answer is still correct with the current version of Rails, I now use the active_scheduler gem created by Justin as mentioned in the answer above: https://stackoverflow.com/a/29155372/1299792
ORIGINAL ANSWER: Avoid using ActiveJob if you need to schedule recurring jobs.
From the issue that Luis raised
As we are not currently supporting recurring jobs with ActiveJob we're going to close this. If it's possible to support recurring jobs I'm seeing this as a separate gem or in rails 5. Feature requests and talks around them are usually talked in the mailing list (https://groups.google.com/forum/#!forum/rubyonrails-core). As a solution to your problem @luismadrigal I suggest you use the resque-scheduler way to do recurring job.
https://github.com/rails/rails/issues/16933#issuecomment-58945932
There was talk about creating a gem in the mailing list but I can't find any further information on it.
It seems that ActiveJob in Rails 4.2 is not supported by resque-scheduler. Therefore, jobs are not scheduled correctly, that explains the difference in the log when a job is enqueued using ActiveJob API and resque-scheduler.
To fix this, we should find a way to schedule job within ActiveJob wrapper:
ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper
Resque-scheduler provides the way to support extensions that are not supported by default. To do this, we should extend custom job class to support the #scheduled
method. This way we can enqueue job manually using ActiveJob API.
The easiest way is to write general code method in the base job, and then extend all jobs from it:
# custom base job
class Job < ActiveJob::Base
# method called by resque-scheduler to enqueue job in a queue
def self.scheduled(queue, klass, *args)
# create the job instance and pass the arguments
job = self.job_or_instantiate(*args)
# set correct queue
job.queue_name = queue
# enqueue job using ActiveJob API
job.enqueue
end
end
Reque-scheduler will call this method to schedule every single job extended from Job
class. This way jobs are going to be enqueued within the ActiveJob wrapper. Result will be same as calling MyJob.perform_later(*args)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With