How do I use the Clockwork Rails scheduler Gem? - ruby-on-rails

I'm having problems with the syntax for the Clockwork scheduler process. I'm actually having similar issues to what is discussed in this thread but never fully answered(How do I use Rails clockwork gem to run rake tasks?)
My 'scheduler.rake' is working correctly when I test it with a 'heroku rake send_notifications'. My clock.rb process is working too as it will trigger every 30 seconds. However, I'm having issues with the clock.rb's syntax to correctly run the 'send_notifications' task in my 'rake.scheduler'. Here's what it looks like:
# scheduler.rake
desc "This task is called by the Heroku scheduler add-on"
task :send_notifications => :environment do
puts "this test is working correctly!"
end
Here's what clock.rb looks like:
require File.expand_path('../../config/boot', __FILE__)
require File.expand_path('../../config/environment', __FILE__)
require 'clockwork'
include Clockwork
every(30.seconds, 'Send notifications') {
# Heroku::API.new.post_ps('pocket-pal', 'rake scheduler:send_notifications')
rake scheduler:send_notifications
}
As you can see I've tried with a detached process using the Heroku API and invoking rake.
When I use the Heroku API, I get this error:
ERROR -- : uninitialized constant Heroku (NameError)
When I invoke rake, I get the following error:
ERROR -- : undefined local variable or method `send_notifications' for main:Object (NameError)
Does anyone know what the correct syntax is for either approach?

This answer works, however you need to follow its string syntax exactly. So in your case:
every(30.seconds, 'Send Notifications') {
`rake scheduler:send_notifications`
}
That means making sure to use ` ` for wrapping the rake task, not " " as that's tripped a few people up.

The docs from Hereko on implementing clockwork might help
Scheduled Jobs and Custom Clock Processes in Ruby with Clockwork

Related

Uninitialized constant 'ActionView' / Don't know how to build task 'environment' in rake task

So, I have actually two issues, but I bet they are connected to each other.
I have to call a rake task on a legacy app (also the task is legacy) but run into "Don't know how to build task 'environment'" and "uninitilized constant" errors. We're working in Rails 5.2 with ruby 2.5.1.
The rake file is in lib/tasks/migrations/models.build_stuff.rb
It looks like this:
include ActionView::Helpers
namespace :migrations do
namespace :build_stuff do
task build_first_things: :environment do
puts 'Starting building first things'
FirstThings.each { |thing| thing.build! }
puts 'Done!'
end
task build_second_things: :environment do
puts 'Starting building second things'
SecondThings.each { |thing| thing.build! }
puts 'Done!'
end
end
end
So, I call the first task with:
rake -f ./lib/tasks/migrations/models/build_first_things.rake migrations:build_stuff:build_first_things
Here I get the following error:
rake aborted!
NameError: uninitialized constant ActionView
I know, in my example there is not even an ActionView helper used, in the real file, there is.
If, just for testing reasons, I delete the line with include ActionView::Helpers another error is raised:
rake aborted!
Don't know how to build task 'environment' (See the list of available tasks with `rake --tasks`)
I don't want to call a task 'environment', just need to load the app and access the database.
Does anyone know, why either (or) both things happen?
Thank you very very much :)
*** Solution ***
It worked when calling bin/railsor bundle exec rakeinstead of simply rake.

How to run clockwork script in production

I am using clockwork gem. I want to automatically delete all comments from comments table every day at midnight.
This app/clock.rb script is working as it supposed to in development env.:
require './config/boot'
require './config/environment'
require 'clockwork'
module Clockwork
every(1.day, 'delete.comment', at: '00:00') {
Comment.destroy_all
}
end
when it's running on my local terminal with $ clockwork app/clock.rb.
So I deployed the app to Heroku. Later in a terminal, I run:
RAILS_ENV=production rails r app/clock.rb
as in this SO topic but only output is:
Running via Spring preloader in process 13973
and it quits to prompt and comments are still there (assuming the value in at: hash has passed).
This is my first individual project.
My question is how to make this script running nonstop in production to remove comments automatically every day at midnight?
OR
more general:
how to run script nonstop in production.
I read this SO topic but the answers are not very thorough and first link above is neither, as for a beginner to understand.
You can create rake task and call form clock.rb
every(1.day, 'name', at: '09:00') do
#Load task
Rake::Task['comment:destroy'].invoke
end
rake task:
lib/tasks/comment.rake
namespace :comment do
desc 'Destroy all comment'
task destroy: :environment do
Comment.destroy_all
end
end
Thanks for effort. After all, I managed this by rake task and without clockwork gem.
I created a rake task, deploy it to heroku, and ran task through heroku scheduler addon. Now it's running as a background job.

How to invoke RSpec inside a rake task?

We wrote some tests that are necessary, but very slow. So we configured RSpec to exclude them except on Solano, where we set up an ENV variable.
# spec_helper
unless ENV['RUN_ALL_TESTS'] == 'true'
config.filter_run_excluding :slow
end
That works, but I'm trying to write a rake task we can call to run every test locally by setting that same ENV variable and then running the suite. I'm having trouble figuring out how to trigger RSpec. This is what I've got now:
# all_tests.rake
require 'rspec/core/rake_task'
desc 'Run all tests, even those usually excluded.'
task all_tests: :environment do
ENV['RUN_ALL_TESTS'] = 'true'
RSpec::Core::RakeTask.new(:spec)
end
When I run it, it doesn't run any tests.
Most of the stuff I found is for triggering a rake task inside of a test, testing a rake task, or setting up a Rakefile. We're using rspec-rails, our default rake task is already set up.
To run RSpec through its rake integration, you need to both define a task and invoke it:
# all_tests.rake
require 'rspec/core/rake_task'
# Define the "spec" task, at task load time rather than inside another task
RSpec::Core::RakeTask.new(:spec)
desc 'Run all tests, even those usually excluded.'
task all_tests: :environment do
ENV['RUN_ALL_TESTS'] = 'true'
Rake::Task['spec'].invoke
end
Rake::Task['spec'].invoke did nothing when you tried it because rake turns a task name which is not a name of a defined task but is a file name into a Rake::FileTask, both on the command line and in Rake::Task. You had no 'spec' task defined, but you have a spec directory, so rake spec ran without error and did nothing.
I had a similar problem where bundle exec rake default would properly create an RSpec::Core::RakeTask, but bundle exec rake spec would instead create a a Rake::FileTask on the spec directory, with with bundle exec rake spec --trace outputting:
** Invoke spec (first_time, not_needed)
It turned out that rspec-rails was in the :test gem group, where it needed (per the docs) to be in both :test and :development.
Interestingly (?), once I did that, gems that had previously only been in the :test group were also available from the specs even when launched with RAILS_ENV=development. I assume that rspec-rails engages in some magic environment shenanigans behind the scenes.

Rails's Rake task takes exceptionally long to execute? [duplicate]

rake --tasks takes about 18s to run. This is just the time it takes to load all the tasks, as a result any task I define will take at least this amount of time to run :
$time rake --tasks
rake db:clean # Cleaning up database
rake passenger:restart # Restart Application
rake spec # Run specs
real 0m18.816s
user 0m7.306s
sys 0m5.665s
My Rakefile :
$: << "."
require "rubygems"
require "rspec/core/rake_task"
desc "Run those specs"
task :spec do
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w{--colour --format progress}
t.pattern = 'spec/*_spec.rb'
end
end
task :default => :spec
Any idea why rake takes to much times ?
Thanks
Try spring
Command line will look like:
spring rake -T
It will take more time running the first time, but subsequent runs will be very fast.
This solution worked for me: Faster rake tasks in Rails.
I had to do a little variation where I created a lib/tasks/no_rails directory and put all the Rake files which do not need Rails in there and loaded only those using the above method.
I like the solution Pratik mentions for the general case of loading rails for tasks that need it and not for those that don't, for any rake task without having to remember beforehand.
A less-invasive method to run a rake task that doesn't need rails is to use the -f rake option to tell rake to use a particular Rakefile. This way, rake won't go looking for rake tasks in all of rails.
For example, assuming your task above is in a file called Rakefile at the top level of your project and your Rakefile doesn't do anything that loads Rails like require File.expand_path('../config/application', __FILE__), you can do:
$ rake -f Rakefile spec
and it should run your spec task much faster. Try $ time rake -f Rakefile -T; I did this with a rails-independent Rakefile of mine and got:
real 0m1.543s
user 0m1.308s
sys 0m0.201s
The downside is you have to remember to specify this option every time, and not to specify it if you want to run a rake task from rails like rake db:migrate.
The entire rails environment has to be loaded, therefore even simple rake tasks such as rake --tasks take a while. Opening a console with rails console or script/console takes a similar time. You may try to hack Ruby or Rails to speed up rake, but too much optimization can be bad if you want to switch to a newer version later. Since the rails environment must be loaded, cleaning up routes may also help.

"undefined method" error when running delayed_jobs in multiple queues with ./script/delayed_job -n

Having a problem with running delayed jobs in multiple queues.
I had the same problem at the beginning when I ran all in one queue with
rake jobs:work
But solved it by running
bundle exec rake jobs:work.
Now for running different queues, I'm using:
./script/delayed_job -n 2 start
and back to start with the error.
The error is:
"Syck::DomainType#{method_name} failed with NoMethodError: undefined method `{method_name}' for #
I have tried to resolve it by adding the code to application.rb as suggested here:
require 'yaml'
YAML::ENGINE.yamler = 'syck'
# [...]
require File.expand_path('../boot', __FILE__)
But it didn't help.
I'm using:
Rails 3.0.9
Ruby 1.9.2 p290
Thanks :)
Moozly.
well, try
bundle exec ./script/delayed_job -n 2 start
;)

Resources