Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit d2eec9f94a43f53eb46fe1bec0ae681b5d874806 @javan committed Feb 16, 2009
@@ -0,0 +1,4 @@
+.DS_Store
+pkg
+doc
+Manifest
@@ -0,0 +1,3 @@
+== 0.1.0 / February 15th, 2008
+
+* Initial release
@@ -0,0 +1,79 @@
+= Whenever
+
+Whenever is a ruby gem that provides a ruby syntax for defining cron jobs. It was designed to work well with Rails applications, but can be used independently as well.
+
+== Installation
+
+To install Whenever in a Rails (2.1 or greater) application:
+
+in your "config/environment.rb" file:
+
+ Rails::Initializer.run do |config|
+ config.gem 'javan-whenever', :lib => 'whenever', :source => 'http://gems.github.com'
+ end
+
+To install this gem (and all other missing gem dependencies), run rake gems:install (use sudo if necessary).
+
+In older versions of Rails:
+
+$ gem sources -a http://gems.github.com
+$ gem install whenever
+
+in your "config/environment.rb" file:
+
+ Rails::Initializer.run do |config|
+ ...
+ end
+
+ require "whenever"
+
+== Getting started
+
+$ cd /my/rails/app
+$ wheneverize .
+
+This will create an initial "config/schedule.rb" file you.
+
+== Example schedule.rb file
+
+ set :runner_path, '/var/www/apps/my_app' # Whenever will try to use your RAILS_ROOT if this isn't set
+ set :runner_environment, :production # Whenever defaults to production so only set this if you want to use a different environment.
+ set :cron_log, '/path/to/my/cronlog.log' # Where to log (this should NOT be your Rails log)
+
+
+ every 2.hours do
+ runner "MyModel.some_process" # runners are the script/runners you know and love
+ command "/usr/local/bin/my_great_command" # commands are any unix command
+ end
+
+ every 1.day, :at => '4:30 am' do # If not :at option is set these jobs will run at midnight
+ runner "DB.Backup", :cron_log => false # You can specify false for no logging or a string a different log file to override logging.
+ end
+
+ every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
+ runner "SomeModel.ladeda"
+ end
+
+ every :sunday do # Use any day of the week or :weekend, :weekday
+ runner "Task.do_something_great"
+ end
+
+== Cron output
+
+$ cd /my/rails/app
+$ whenever
+
+And you'll see your schedule.rb converted to cron sytax
+
+== Capistrano integration
+
+Use the "whenever:write_cron" task to automatically write your crontab file with each deploy.
+
+in your "config/deploy.rb" file do something like:
+
+ after "deploy:symlink", "whenever:write_cron"
+
+THIS WILL COMPLETELY OVERWRITE ANY EXISTING CRONTAB ENTRIES!
+------------------------------------------------------------
+
+Better documentation on the way!
@@ -0,0 +1,14 @@
+require 'rubygems'
+require 'rake'
+require 'echoe'
+require 'lib/base'
+
+Echoe.new('whenever', Whenever::VERSION) do |p|
+ p.description = "Provides (clean) ruby syntax for defining (messy) cron jobs and running them Whenever."
+ p.url = "http://github.com/javan/whenever"
+ p.author = "Javan Makhmali"
+ p.email = "javan@javan.us"
+ p.dependencies = ["chronic", "activesupport"]
+ p.ignore_pattern = ["tmp/*", "script/*"]
+ p.development_dependencies = []
+end
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+
+require 'rake'
+require 'optparse'
+require 'whenever'
+
+task = "whenever:output_cron"
+
+OptionParser.new do |opts|
+ opts.banner = "Usage: whenever [options]"
+ opts.on('-c', '--write-crontab') { task = "whenever:write_cron" }
+ opts.on('-v', '--version') { puts "Whenever v#{Whenever::VERSION}"; exit }
+end.parse!
+
+Rake::Task[task].invoke
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+
+# This file is based heavily on Capistrano's `capify` command
+
+require 'optparse'
+
+OptionParser.new do |opts|
+ opts.banner = "Usage: #{File.basename($0)} [path]"
+
+ begin
+ opts.parse!(ARGV)
+ rescue OptionParser::ParseError => e
+ warn e.message
+ puts opts
+ exit 1
+ end
+end
+
+if ARGV.empty?
+ abort "Please specify the directory to wheneverize, e.g. `#{File.basename($0)} .'"
+elsif !File.exists?(ARGV.first)
+ abort "`#{ARGV.first}' does not exist."
+elsif !File.directory?(ARGV.first)
+ abort "`#{ARGV.first}' is not a directory."
+elsif ARGV.length > 1
+ abort "Too many arguments; please specify only the directory to wheneverize."
+end
+
+
+content = <<-FILE
+# Use this file to easily define all of your cron jobs.
+#
+# It's helpful, but not entirely necessary to understand cron before proceeding.
+# http://en.wikipedia.org/wiki/Cron
+
+# Example:
+#
+# set :cron_log, "/path/to/my/cron_log.log"
+#
+# every 2.hours do
+# command "/usr/bin/some_great_command"
+# runner "MyModel.some_method"
+# end
+#
+# every 4.days do
+# runner "AnotherModel.prune_old_records"
+# end
+
+# Learn more: http://github.com/javan/whenever
+FILE
+
+file = 'config/schedule.rb'
+base = ARGV.shift
+
+file = File.join(base, file)
+if File.exists?(file)
+ warn "[skip] `#{file}' already exists"
+elsif File.exists?(file.downcase)
+ warn "[skip] `#{file.downcase}' exists, which could conflict with `#{file}'"
+elsif !File.exists?(File.dirname(file))
+ warn "[skip] directory `#{File.dirname(file)}' does not exist"
+else
+ puts "[add] writing `#{file}'"
+ File.open(file, "w") { |f| f.write(content) }
+end
+
+puts "[done] wheneverized!"
@@ -0,0 +1,12 @@
+require 'job_list'
+require 'job_types/default'
+require 'job_types/runner'
+require 'outputs/cron'
+
+module Whenever
+ VERSION = '0.1.0'
+
+ def self.cron(options)
+ Whenever::JobList.new(options).generate_cron_output
+ end
+end
@@ -0,0 +1,84 @@
+module Whenever
+ class JobList
+
+ def initialize(options)
+ @jobs = Hash.new
+ @env = Hash.new
+
+ config = case options
+ when String then options
+ when Hash
+ if options[:string]
+ options[:string]
+ elsif options[:file]
+ File.read(options[:file])
+ end
+ end
+
+ eval(config)
+ end
+
+ def set(variable, value)
+ instance_variable_set("@#{variable}".to_sym, value)
+ self.class.send(:attr_reader, variable.to_sym)
+ end
+
+ def env(variable, value)
+ @env[variable.to_s] = value
+ end
+
+ def every(frequency, options = {})
+ @current_time_scope = frequency
+ @options = options
+ yield
+ end
+
+ def command(task, options = {})
+ options[:cron_log] ||= @cron_log unless options[:cron_log] === false
+ options[:class] ||= Whenever::Job::Default
+ @jobs[@current_time_scope] ||= []
+ @jobs[@current_time_scope] << options[:class].new(@options.merge(:task => task).merge(options))
+ end
+
+ def runner(task, options = {})
+ options.reverse_merge!(:environment => @runner_environment, :path => @runner_path)
+ options[:class] = Whenever::Job::Runner
+ command(task, options)
+ end
+
+ def generate_cron_output
+ [environment_variables, cron_jobs].compact.join
+ end
+
+ private
+
+ def environment_variables
+ return if @env.empty?
+
+ output = []
+ @env.each do |key, val|
+ output << "#{key}=#{val}\n"
+ end
+ output << "\n"
+
+ output.join
+ end
+
+ def cron_jobs
+ return if @jobs.empty?
+
+ output = []
+ @jobs.each do |time, jobs|
+ jobs.each do |job|
+ cron = Whenever::Output::Cron.output(time, job)
+ cron << " >> #{job.cron_log} 2>&1" if job.cron_log
+ cron << "\n\n"
+ output << cron
+ end
+ end
+
+ output.join
+ end
+
+ end
+end
@@ -0,0 +1,17 @@
+module Whenever
+ module Job
+ class Default
+ attr_accessor :task, :at, :cron_log
+
+ def initialize(options = {})
+ @task = options[:task]
+ @at = options[:at]
+ @cron_log = options[:cron_log]
+ end
+
+ def output
+ task
+ end
+ end
+ end
+end
@@ -0,0 +1,30 @@
+module Whenever
+ module Job
+ class Runner < Whenever::Job::Default
+
+ def initialize(options = {})
+ super(options)
+
+ @environment = options[:environment] || :production
+
+ if [Whenever::Job::Runner.rails_root, options[:path]].all?(&:blank?)
+ raise ArgumentError, "no cron_path available for runner to use"
+ else
+ @path = options[:path] || Whenever::Job::Runner.rails_root
+ end
+ end
+
+ def self.rails_root
+ if defined?(RAILS_ROOT)
+ RAILS_ROOT
+ elsif defined?(::RAILS_ROOT)
+ ::RAILS_ROOT
+ end
+ end
+
+ def output
+ %Q(#{File.join(@path, 'script', 'runner')} -e #{@environment} "#{task}")
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit d2eec9f

Please sign in to comment.