How to run clockwork script in production - ruby-on-rails

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.

Related

How to test rake tasks with Whenever Gem?

I'm trying to execute a simple rake task using whenever gem but the code isn't being executed.
I already set the environment to development, I updated the cron using the whenever --update-crontab command and the rake task works well if I run the command on console. But, when I run the server the log file is not being generated.
I saw a question here too with the same problem but it was solved setting the environment to development, but didn't work out for me.
My rake task:
namespace :testando do
task :consulta => :environment do
produto = Produto.first
puts produto.nm_produto
end
end
My schedule.rb:
set :output, "#{path}/log/cron_log.log"
set :environment, 'development'
every 1.minute do
rake "testando:consulta"
end
I'm using rails 5.0.0.1 and I'm programing in Cloud9, so I think the OS is Ubuntu.
What's missing ?
Update:
I followed the instructions of the main answer in this topic Cron job not working in Whenever gem
And it worked! The task is running even with the server not being started (with "rails s" command).
please run crontab -l to see if you have updated the crontab successfully

Cron job not being updated by whenever gem

Having a series of rake tasks that should be translated by the whenever gem into the cron file, I was wondering why the takes shows were pointing to an old release.
It cannot be asserted that whenever is active somehow, even though it is listed in the gem file (and associated lock file) and deployment refers to whenever in the deployment as follows:
tar: DEBUG [1f7d4e56] bin/whenever: time stamp 2016-01-08 15:01:20 is 88.787104175 s in the future
update Checking bundle exec whenever -v returns the proper version. Need bundle exec there...
Capfile includes require "whenever/capistrano" after calls to bundler and rails.
require 'capistrano/bundler'
require 'capistrano/rails'
require 'whenever/capistrano'
Note: this is being tested in development mode.
Functional answer. The instructions are misleading If you don't need different jobs running on different servers in your capistrano deployment, then you can safely stop reading now and everything should just work the same way it always has. Keep on reading.
The nugget is nested after this statement. Roles default to [:db]. Thus two sources of error are possible:
different job_roles on different machines are not specified in schedule.rb
Check your environment file. If "db" is not listed, whenever will not fire.
I had the same issues with using Capistrano whenever plugin, I solved it by making custom deploy shell scripts, cap production deploy being one command of many, and then inclding cap production cron:regen; inside this script I called deploy.sh, with the command inside the deploy.rb being:
namespace :cron do
desc "restart cron"
task :regen do
on roles(:app) do |host|
rails_env = fetch(:stage)
execute_interactively "crontab -r;bundle exec whenever --update-crontab;crontab -l;"
end
end
end
def execute_interactively(command)
port = fetch(:port) || 22
exec "ssh root##{fetch(:ip)} -t 'cd SERVER_PATH_OF_YOUR_APP && #{command}'"
end
I use these functions for all types of different commands, since Capistrano still gives me problems with a lot of native plugins it uses.
If you're not happy with the whenever/capistrano, you can create yourself a simple Capistrano task to update the cron jobs:
namespace :deploy do
desc "Update crontab with whenever"
task :update_cron do
on roles(:app) do
within current_path do
execute :bundle, :exec, "whenever --update-crontab #{fetch(:application)}"
end
end
end
after :finishing, 'deploy:update_cron'
end
The task will be called when the code deployment is finished.

Rails - Run Rake tasks with Capistrano

Im scratching my head here wondering if I'm barking up the wrong tree. I have a server which I've deployed a Rails app onto using Capistrano. Recently I added a new data type to one of the models, and now I need to run a Rake task to update the existing records.
After a lot of Googling I'm starting to wonder if people use Rake tasks with Capistrano. Some forum posts from 2013 or so mention that Capistrano supports the .rake extension. Whereas other posts I've found indicate that Capistrano has its own task automation system, and is incompatible with rake.
I found Cape, but I'm unsure if this is what I'm looking for as it seems to convert Rake tasks into cap recipes. Its possible I'm mistaken on this point, I really don't have any experience working with Capistrano or even working in the full stack spectrum.
What I'm wondering is this: How do I run a simple Rake task on my remote server?
Some quick points for clarity, I've installed the app on the latest Ubuntu LTS, 14.10 if memory serves. I followed the tutorial found here. I have full sudo access and I can ssh into the server.
thanks in advance for helping a noob
If you need to update models, you can of course write a Rails migration - this will ensure that it's run if it hasn't been run yet.
The easiest way to execute a rake task on the server would be just via ssh if it's a one-time task. See the last paragraph in the tutorial you mentioned:
cd /opt/www/testapp/current ; bin/rake RAILS_ENV=production db:seed
To answer your original question about rake: you can execute rake tasks via capistrano similar to how you would execute it locally, only within the capistrano script. Here's an example:
deploy.rb:
namespace :rake do
desc "My task"
task :my_task do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, "my_task"
# !!!see NOTE at end of answer!!!
end
end
end
end
end
You can view all your cap tasks via cap -T locally. The capistrano task I wrote above should show up as cap tasks:my_rake_task.
If you want to be ably to run any available rake task without configuring, do the following:
namespace :rake do
desc "Invoke rake task"
task :invoke do
on roles(:app) do
within "#{current_path}" do
with rails_env: :production do
execute :rake, ENV['task']
# !!!see NOTE at end of answer!!!
end
end
end
end
end
Then you can write:
cap production deploy:invoke task=my:rake:task
NOTE: you might want to replace the execution line with
run "bin/rake RAILS_ENV=#{rails_env} #{ENV['task']}"
to use the same syntax as the tutorial (without the binstubs you might need to configure capistrano/bundler and capistrano/rbenv first ...)
Check out capistrano-rake
Once installed, run any rake task on your production/staging servers without messy capistrano recipes by simply doing this:
$ cap production invoke:rake TASK=your:rake:task
Full Disclosure: I wrote it

How to run only rake task once

I am using Ruby on Rails and Heroku.
I would like something like rake db:migrate, where it will only run the parts that have not been run before.
I can set a rake task that can run other rake task, but is there in way to only run those that did not run before?
What are any alternative, if I want rake tasks to be run automatically?
first of, running a rake task twice, ie rake db:migrate will neither duplicate nor overwrite your database columns if they already exist.
For example capistrano, used to deploy your rails app to basically anywhere, will rerun tasks like db:migrateor assets:precompile every time you deploy your app. So no need to worry about that really.
To run tasks automatically you will need something like a cron job. Whenever is a great ruby gem that allows you to install a job like this with the beloved ruby syntax.
After installing the gem and running wheneverize . in the root of your rails app, you may edit the scheduler.rb and add something like:
every :sunday, :at => '12pm' do
rake my:awesome:task
end
The Github page as well as the default scheduler.rb hold many useful examples of how these jobs are built.
with whenever --update-crontab you can write your rubyesque cronjobs into the crontab, which will run your tasks periodically at the time you want them to.
** edit
multiple tasks in one:
task :setup => [:a, :b, :c]
task :a do
%x(bash command)
end
task :b do
rake db:migrate
end
task :c do
rake whatever
end

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.

Resources