I'm really new to rails. I'm trying to learn how to write a cron job with a rake task to send daily digest emails. How should I go about doing this?
I'm guessing that I write a loop in the task to go through each user and compile and email. Then I send it inside the for loop.
How do I set this rake task as a cron job so that it runs in the background? This seems like it should be super simple, but I feel like I'm missing something.
One way to do this, as you've visualized already, is to define a rake task which would run at a scheduled time. Crontab is best for that if you're on a Linux system. Following are the steps you would follow to do that:
The rake task with the logic of fetching the emails to send digest emails.
A shell script, digest.sh which would load up and run the rake task. Something like this:
cd /your/app /usr/bin/rake utils:sendNotifications > /your/app/log/notifications.log
We're telling it to go into your application folder ( /your/app ), run the rake task utils:sendNotifications and log the output in log/notifications.log
And finally, schedule tasks on Linux using crontab.
Related
I'm currently using Heroku's scheduler to run a script. However, the time that the script takes to run is going to increase from a few milliseconds to a few minutes. I'm looking at using the delayed_job gem to push this process off to a Worker Dyno. I want to continue to run this script once-a-day, just offload it to the worker. My current rake task is:
desc "This task updates some stuff for you."
task :update_some_stuff => :environment do
puts "Updating some stuff ..."
SomeClass.new.process
puts "... done."
end
Once the gem is installed, migration run, and worker dyno started, will the script just need to change to:
desc "This task updates some stuff for you."
task :update_some_stuff => :environment do
puts "Updating some stuff ..."
SomeClass.new.delay.process
puts "... done."
end
With this task still being a rake task scheduled by Heroku's Scheduler, is the only thing that needs to happen here the introduction of the delay method to put this in the Worker's queue?
Thanks in advance for any help.
Yes, DJ is a very simple gem, and you should be able to see this working correctly locally by adding a record to your delayed_jobs table in your database. With a worker running on Heroku everything should be fine.
Just make sure you have the following in your Procfile:
worker: bundle exec rake jobs:work
More information can be found here: https://devcenter.heroku.com/articles/delayed-job
I'm barely started to use Jenkins and this is the first problem I've had so far. Basically my jenkins job always succeed even when an error happened in some of the tests. This is what I'm running in the shell config:
bundle install
rake db:migrate:reset
rake test:units
rake spec:models
Thing is that Jenkins only reports a failure when the task which fails is the last one. For instance, if I put "rake test:units" the last task it will notify an error if something go wrong. Using this configuration I only get error reports for the rspec tests but not for the unit tests.
Anyone wondering why I don't only use rspec or unit test, we are currently migrating to rspec but this problem is still painful.
This is part of the log from Jenkinsm as you can see one of the unit test fails but jenkins still finish with success.
314 tests, 1781 assertions, 1 failures, 0 errors, 0 skips
rake aborted!
Command failed with status (1): [/var/lib/jenkins/.rvm/rubies/ruby-1.9.3-p1...]
Tasks: TOP => test:units
(See full trace by running task with --trace)
Lot of rspec tests here....
Finished in 3.84 seconds
88 examples, 0 failures, 42 pending
Pushing HEAD to branch master of origin repository
Pushing HEAD to branch master at repo origin
Finished: SUCCESS
Jenkins executes the commands you type into a Build Step box by writing them to a temporary file and then running the script using /bin/sh -xe.
Usually this produces the desired effect: Commands are executed in sequence (and printed) and the script aborts immediately when a command fails i.e. exits with non-zero exit code.
If this is not happening to you, the only reason can be that you have overridden this behavior. You can override it by starting the first line of your Build Step with these two characters: #!.
For example, if your Build Step looks like this:
#!/bin/bash
bundle install
rake db:migrate:reset
rake test:units
rake spec:models
Then it means Jenkins will write the script to a temporary file and it will be executed with /bin/bash. When invoked like that, bash will execute commands one-by-one and not care if they succeed. The exit code of the bash process will be the exit code of the last command in the script and that will be seen by Jenkins when the script ends.
So, take care in what you put on the first line of the Build Step. If you do not know how shell works, do not put a hash-bang at all and let Jenkins decide how the script should be run.
If you need more control over how the Build Step is executed, you should study the man page of the shell you use to find out how to make it behave the way you want. Jenkins doesn't have much of a role in here. It just executes the shell you wanted the way you wanted.
Jenkins can only see the result code of the last command run so it has no way of knowing what the result of rake test:units is.
The easiest thing is probably to have each command of those commands as a separate jenkins build step.
An alternative solution is change your first line to the following:
#!/bin/bash -e
This tells your script to fail if any of the commands in the script return an error.
See: Automatic exit from bash shell script on error
# lib/tasks/test.rake
task :hello do
puts 'hello'
end
$ rake app:hello
To run the task I need to prefix it with "app:" and it runs in the context of the dummy app. It is also exposed to the host application (i.e when used as a plugin in a parent Rails app) as rake hello.
I want to run a rake task which does not require a Rails environment and runs some command, but it is run from the engine root, not the dummy app root.
I know that's a bit late, but for others here searching for the correct answer, do the following :
Create your task :
# lib/tasks/your_engine_tasks.rake
desc "Explaining what the task does"
task :your_task do
# Task goes here
end
Then go to your engine ./Rakefile and add
load 'lib/tasks/your_engine_tasks.rake'
Here we go, now:
$ rake -T
gives you your task.
Hope I helped.
I want a better answer to this question however I did figure out that you can add tasks in the Rakefile for the engine (so ./Rakefile not in the spec/dummy application) like so:
task :my_task do
puts "hi!"
end
task :default => [:spec, :my_task]
I would prefer to have my task in another file but at least this provides a way to go forward. In my case, I want to run Konacha javascript tests in the dummy application so my Rakefile looks like this:
task :spec_javascript do
exec 'cd spec/dummy && rake konacha:run' # exec passes command return value up stack!
end
task :default => [:spec, :spec_javascript]
I'm using delayed_job and I am able to run jobs using rake jobs:work but using the daemonized version, it does nothing although I see it in the process list.
I'm using:
rails (3.0.9)
delayed_job (2.1.4)
daemons (1.0.10)
I'm running delayed_job using:
unix>RAILS_ENV=development script/delayed_job start
It could be a problem loading a custom job class file. To test that, try this:
Enter the rails console rails console --sandbox.
Make sure you have a job in the table job = Delayed::Job.first.
Try YAML.load(job.handler). If you get an error that looks like this: ArgumentError: undefined class/module MyCustomClass, it's probably a problem loading your custom job
Still in the rails console, run require 'My_Custom_Class. Then run the YAML.load(job.handler) command again. If this returns the appropriate object it's definitely a class loading problem.
To fix the problem create the file config/initializers/custom.rb and in it put require 'My_Custom_Class'.
You should then be able to run rake jobs::workoff and get something that looks like this:
[Worker(host:my.host pid:5085)] Starting job worker
[Worker(host:my.host pid:5085)] MyCustomJob completed after 0.0774
[Worker(host:my.host pid:5085)] 1 jobs processed at 9.1935 j/s, 0 failed ...
[Worker(host:my.host pid:5085)] No more jobs available. Exiting
To answer your question we may need more information.
Are jobs added to database? Are there any errors in jobs?
What's the result of RAILS_ENV=development script/delayed_job status as I already mentioned?
Second, did you went through the most common problems Wiki page?
https://github.com/collectiveidea/delayed_job/wiki/Common-problems
I would like to get the status of a Rake Task into my backoffice(That means Running or not running).
And I also would like to start the rake task if it is not running. Otherwise I want to quit it.
Any idea?
You can look at this part of a gist: https://gist.github.com/1003601#file_delayed_delta.sh
Basically, I save the PID of the rake task to PIDFILE, then use monit to see if it is running.
https://gist.github.com/1003601#file_monitrc
You could also have a cronjob that runs a system command like ps -ef | grep my_rake_task and see if anything turns up. This may or may not require less effort.