From aabd97b0073c7a0012741d18fbe0e94704a9dce5 Mon Sep 17 00:00:00 2001 From: Bernabas Date: Fri, 4 Dec 2015 23:23:08 -0500 Subject: [PATCH 1/3] add support for multiple servers --- bin/whenever_server | 38 ++++++++++++++++++++++++++++++++++++++ lib/whenever/job_list.rb | 5 +++++ lib/whenever/setup.rb | 3 +++ whenever.gemspec | 2 +- 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100755 bin/whenever_server diff --git a/bin/whenever_server b/bin/whenever_server new file mode 100755 index 00000000..8bd72528 --- /dev/null +++ b/bin/whenever_server @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby + +require 'whenever' +require 'redis' + +options = {} + +OptionParser.new do |opts| + opts.banner = "Usage: whenever [options]" + + opts.on('-f', '--load-file [schedule file]', 'Default: config/schedule.rb') do |file| + options[:file] = file if file + end +end.parse! + +job_list = Whenever::JobList.new(file: options[:file] || 'config/schedule.rb') + +puts(false) unless job_list.redis_options + +redis = Redis.new(job_list.redis_options) + +# redis key +lock = :whenever_server + +# get the server that has the lock +whenever_server = redis.get lock + +# if there is no server with the lock, give the lock to the current server +if whenever_server.nil? + redis.multi do + redis.setnx lock, Socket.gethostname + # expire hourly + redis.expire lock, 3600 + end +end + +# return true/false if the current server should be running the task or not +puts redis.get(lock) == Socket.gethostname \ No newline at end of file diff --git a/lib/whenever/job_list.rb b/lib/whenever/job_list.rb index be208048..5f748a26 100644 --- a/lib/whenever/job_list.rb +++ b/lib/whenever/job_list.rb @@ -21,6 +21,8 @@ def initialize(options) File.read(options[:file]) end + @file = options[:file] + instance_eval(Whenever::NumericSeconds.process_string(setup), setup_file) instance_eval(Whenever::NumericSeconds.process_string(schedule), options[:file] || '') end @@ -48,6 +50,9 @@ def job_type(name, template) singleton_class_shim.class_eval do define_method(name) do |task, *args| options = { :task => task, :template => template } + + options[:template] = "cd :path && if whenever_server #{ "-f #{@file}" if @file && @file != 'config/schedule.rb'} >> /dev/null; then #{options[:template]} ; fi" if @redis_options + options.merge!(args[0]) if args[0].is_a? Hash # :cron_log was an old option for output redirection, it remains for backwards compatibility diff --git a/lib/whenever/setup.rb b/lib/whenever/setup.rb index e2a02c41..b8009827 100644 --- a/lib/whenever/setup.rb +++ b/lib/whenever/setup.rb @@ -9,6 +9,9 @@ # http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production set :job_template, "/bin/bash -l -c ':job'" +# Multiple servers support +set :redis_options, nil + set :runner_command, case when Whenever.bin_rails? "bin/rails runner" diff --git a/whenever.gemspec b/whenever.gemspec index 970566f3..6c7d7bce 100644 --- a/whenever.gemspec +++ b/whenever.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.add_dependency "chronic", ">= 0.6.3" - + s.add_dependency "redis" s.add_development_dependency "mocha", ">= 0.9.5" s.add_development_dependency "rake" s.add_development_dependency "minitest" From 048465d7dd9390e7af13af820a73a3811be30915 Mon Sep 17 00:00:00 2001 From: Bernabas Date: Sat, 5 Dec 2015 00:42:40 -0500 Subject: [PATCH 2/3] include spec and clean up --- lib/whenever/job_list.rb | 4 ++-- test/functional/output_whenever_server_test.rb | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 test/functional/output_whenever_server_test.rb diff --git a/lib/whenever/job_list.rb b/lib/whenever/job_list.rb index 5f748a26..30667b39 100644 --- a/lib/whenever/job_list.rb +++ b/lib/whenever/job_list.rb @@ -21,7 +21,7 @@ def initialize(options) File.read(options[:file]) end - @file = options[:file] + @options = options instance_eval(Whenever::NumericSeconds.process_string(setup), setup_file) instance_eval(Whenever::NumericSeconds.process_string(schedule), options[:file] || '') @@ -51,7 +51,7 @@ def job_type(name, template) define_method(name) do |task, *args| options = { :task => task, :template => template } - options[:template] = "cd :path && if whenever_server #{ "-f #{@file}" if @file && @file != 'config/schedule.rb'} >> /dev/null; then #{options[:template]} ; fi" if @redis_options + options[:template] = "cd :path && if whenever_server #{ "-f #{@options[:file]}" if @options[:file] && @options[:file] != 'config/schedule.rb'} >> /dev/null ; then #{options[:template]} ; fi" if @redis_options options.merge!(args[0]) if args[0].is_a? Hash diff --git a/test/functional/output_whenever_server_test.rb b/test/functional/output_whenever_server_test.rb new file mode 100644 index 00000000..3e7fe257 --- /dev/null +++ b/test/functional/output_whenever_server_test.rb @@ -0,0 +1,16 @@ +require 'test_helper' + +class OutputWheneverServer < Whenever::TestCase + test 'command when the redis_options is set' do + output = Whenever.cron \ + <<-file + set :redis_options, url: 'redis://localhost:6379/1' + every :hour do + set :path, "/tmp" + command "blahblah" + end + file + + assert_match "0 * * * * /bin/bash -l -c 'cd /tmp && if whenever_server >> /dev/null ; then blahblah ; fi'", output + end +end \ No newline at end of file From 48eb9dcbdf621ab371f37acf8071ebbba0deb992 Mon Sep 17 00:00:00 2001 From: Bernabas Date: Sat, 5 Dec 2015 01:07:56 -0500 Subject: [PATCH 3/3] make syntax compatable with 1.8.7 --- test/functional/output_whenever_server_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/output_whenever_server_test.rb b/test/functional/output_whenever_server_test.rb index 3e7fe257..3586511a 100644 --- a/test/functional/output_whenever_server_test.rb +++ b/test/functional/output_whenever_server_test.rb @@ -4,7 +4,7 @@ class OutputWheneverServer < Whenever::TestCase test 'command when the redis_options is set' do output = Whenever.cron \ <<-file - set :redis_options, url: 'redis://localhost:6379/1' + set :redis_options, :url => 'redis://localhost:6379/1' every :hour do set :path, "/tmp" command "blahblah"