scheduler_daemon_robertcigan 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -0
- data/Gemfile.lock +35 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +146 -0
- data/Rakefile +71 -0
- data/VERSION +1 -0
- data/bin/scheduler_daemon +59 -0
- data/lib/loader/scheduler_loader.rb +12 -0
- data/lib/scheduler_daemon.rb +2 -0
- data/lib/scheduler_daemon/base.rb +149 -0
- data/lib/scheduler_daemon/command_line_args_to_hash.rb +47 -0
- data/lib/scheduler_daemon/exception_handler.rb +30 -0
- data/lib/scheduler_daemon/rails/generators/scheduler/USAGE +6 -0
- data/lib/scheduler_daemon/rails/generators/scheduler/scheduler_generator.rb +16 -0
- data/lib/scheduler_daemon/rails/generators/scheduler/templates/README +11 -0
- data/lib/scheduler_daemon/rails/generators/scheduler/templates/lib/scheduled_tasks/session_cleaner_task.rb +29 -0
- data/lib/scheduler_daemon/rails/generators/scheduler_task/scheduler_task_generator.rb +21 -0
- data/lib/scheduler_daemon/rails/generators/scheduler_task/templates/README +14 -0
- data/lib/scheduler_daemon/rails/generators/scheduler_task/templates/scheduled_tasks/example_task.rb +19 -0
- data/lib/scheduler_daemon/rails/railtie.rb +9 -0
- data/lib/scheduler_daemon/scheduler_task.rb +78 -0
- data/scheduler_daemon_robertcigan.gemspec +82 -0
- data/spec/command_line_args_to_hash_spec.rb +26 -0
- data/spec/scheduled_tasks/session_cleaner_task_spec.rb +35 -0
- data/spec/scheduler_spec.rb +21 -0
- data/spec/spec_helper.rb +16 -0
- metadata +140 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
scheduler_daemon_robertcigan (1.1.3)
|
5
|
+
activesupport
|
6
|
+
chronic (>= 0.2.0)
|
7
|
+
daemons (>= 1.0.10)
|
8
|
+
eventmachine (>= 0.12.8)
|
9
|
+
rufus-scheduler (>= 2.0.1)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
activesupport (3.2.12)
|
15
|
+
i18n (~> 0.6)
|
16
|
+
multi_json (~> 1.0)
|
17
|
+
chronic (0.9.1)
|
18
|
+
daemons (1.1.9)
|
19
|
+
eventmachine (1.0.0)
|
20
|
+
i18n (0.6.2)
|
21
|
+
multi_json (1.6.1)
|
22
|
+
rufus-scheduler (2.0.17)
|
23
|
+
tzinfo (>= 0.3.23)
|
24
|
+
tzinfo (0.3.35)
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
ruby
|
28
|
+
|
29
|
+
DEPENDENCIES
|
30
|
+
activesupport
|
31
|
+
chronic (>= 0.2.0)
|
32
|
+
daemons (>= 1.0.10)
|
33
|
+
eventmachine (>= 0.12.8)
|
34
|
+
rufus-scheduler (>= 2.0.1)
|
35
|
+
scheduler_daemon_robertcigan!
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Steven Soroka
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
Scheduler Daemon
|
2
|
+
================
|
3
|
+
|
4
|
+
Rails 3+ compatible scheduler daemon (see branches for older versions).
|
5
|
+
|
6
|
+
Replaces cron/rake pattern of periodically running rake tasks
|
7
|
+
to perform maintenance tasks in Rails apps. Scheduler Daemon is made specifically for your Rails app,
|
8
|
+
and only loads the environment once, no matter how many tasks run.
|
9
|
+
|
10
|
+
What's so great about it? Well, I'm glad you asked!
|
11
|
+
|
12
|
+
- Only loads your Rails environment once on daemon start, not every time a task is run
|
13
|
+
- Allows you to easily deploy the scheduled tasks with your Rails app instead of depending on an
|
14
|
+
administrator to update crontab
|
15
|
+
- Can be installed as a gem or a plugin (I suggest gem)
|
16
|
+
- It doesn't use rake or cron!
|
17
|
+
- Gets you up and running with your own daemon in under 2 minutes
|
18
|
+
- Specially designed to work with your rails app!
|
19
|
+
|
20
|
+
Setup
|
21
|
+
=====
|
22
|
+
|
23
|
+
Install as a gem or plugin.
|
24
|
+
|
25
|
+
As a gem, the old-fashioned way:
|
26
|
+
|
27
|
+
gem install scheduler_daemon
|
28
|
+
|
29
|
+
As a gem with bundler, add to your ./Gemfile:
|
30
|
+
|
31
|
+
gem 'scheduler_daemon'
|
32
|
+
|
33
|
+
I pretty much assume you chose this option below and prefix most commands with "bundle exec"
|
34
|
+
|
35
|
+
As a plugin: (might be awkward to call the binary to start up the daemon...)
|
36
|
+
|
37
|
+
script/plugin install git://github.com/ssoroka/scheduler_daemon.git
|
38
|
+
# Install required gems
|
39
|
+
gem install daemons rufus-scheduler eventmachine chronic -s http://gemcutter.org
|
40
|
+
|
41
|
+
Optionally generate the default scheduler daemon task for your rails app:
|
42
|
+
|
43
|
+
script/rails generate scheduler_task MyNewTask
|
44
|
+
|
45
|
+
which will create an task named:
|
46
|
+
|
47
|
+
scheduled_tasks/my_new_task.rb
|
48
|
+
|
49
|
+
Usage
|
50
|
+
=====
|
51
|
+
|
52
|
+
generate a new scheduled task:
|
53
|
+
|
54
|
+
script/rails generate scheduler_task MyTaskName
|
55
|
+
|
56
|
+
If you have problems with that, the template for new tasks is in the gem under:
|
57
|
+
|
58
|
+
lib/scheduler_daemon/rails/generators/scheduler_task/templates/scheduled_tasks/example_task.rb
|
59
|
+
|
60
|
+
you can always copy it and make modifications, or see "Manually create tasks" below.
|
61
|
+
|
62
|
+
Tasks support their own special DSL; commands are:
|
63
|
+
|
64
|
+
environments :production, :staging # run only in environments listed. (:all by default)
|
65
|
+
every '1d' # run every day
|
66
|
+
every '1d', :first_at => Chronic.parse("2 am") # run every day, starting at 2 am (see caveat below)
|
67
|
+
at Cronic.parse('5 pm') # run *once* at 5 pm today
|
68
|
+
# (relative to scheduler start/restart time )
|
69
|
+
# (happens every time scheduler starts/restarts)
|
70
|
+
# (see caveat below )
|
71
|
+
cron '* 4 * * *' # cron style (run every 4 am)
|
72
|
+
in '30s' # run once, 30 seconds from scheduler start/restart
|
73
|
+
|
74
|
+
fire up the daemon in console mode to test it out
|
75
|
+
|
76
|
+
bundle exec scheduler_daemon run
|
77
|
+
|
78
|
+
For production environments, add the daemon to the system start-up, and
|
79
|
+
capistrano deploy scripts, etc. Something like:
|
80
|
+
|
81
|
+
export RAILS_ENV=production
|
82
|
+
bundle exec scheduler_daemon start
|
83
|
+
|
84
|
+
Selectively run tasks like so:
|
85
|
+
|
86
|
+
bundle exec scheduler_daemon start -- --only=task_name1,task_name2 --except=not_me
|
87
|
+
|
88
|
+
Manually create tasks
|
89
|
+
=====================
|
90
|
+
|
91
|
+
If you don't want to use this gem with Rails, you can manually create tasks in a scheduled_tasks/ subdirectory and start the daemon with --skip-rails (though it'll figure it out anyway if there's no config/environment.rb file in the launch directory or --dir=/path)
|
92
|
+
|
93
|
+
Here's an example task file.
|
94
|
+
|
95
|
+
class CleanUpTask < Scheduler::SchedulerTask
|
96
|
+
every '2m'
|
97
|
+
|
98
|
+
def run
|
99
|
+
do_something
|
100
|
+
log("I've done things")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Specs
|
105
|
+
=====
|
106
|
+
|
107
|
+
See the spec for session cleaner for an idea on how to write specs for your tasks
|
108
|
+
|
109
|
+
To Do
|
110
|
+
=====
|
111
|
+
|
112
|
+
Looking for suggestions!
|
113
|
+
|
114
|
+
Send requests to ssoroka78@gmail.com or on twitter, @ssoroka
|
115
|
+
|
116
|
+
Bugs
|
117
|
+
====
|
118
|
+
|
119
|
+
Submit bugs here http://github.com/ssoroka/scheduler_daemon/issues
|
120
|
+
|
121
|
+
Caveats
|
122
|
+
=======
|
123
|
+
|
124
|
+
When using the cronic gem to parse dates, be careful of how it interprets your date,
|
125
|
+
for example:
|
126
|
+
|
127
|
+
every '24h', :first_at => Chronic.parse('noon')
|
128
|
+
|
129
|
+
will be once a day at noon, but the first time the server starts up (or restarts), noon
|
130
|
+
is relative to the current time of day. Before lunch, and it's in the future. If the
|
131
|
+
daemon starts up after lunch, the date is in the past, *and the task is immediately run*
|
132
|
+
because it thinks it missed its last execution time. Depending on what your task is,
|
133
|
+
this may or may not be a problem. If you always want the date to resolve in the future
|
134
|
+
with terms like "noon", "3 am" and "midnight", prepend "next" to it. ie:
|
135
|
+
|
136
|
+
every '24h', :first_at => Chronic.parse('next noon')
|
137
|
+
|
138
|
+
Author
|
139
|
+
======
|
140
|
+
|
141
|
+
Steven Soroka
|
142
|
+
|
143
|
+
* [@ssoroka](http://twitter.com/ssoroka)
|
144
|
+
* [My Github repo](http://github.com/ssoroka)
|
145
|
+
* [My blog](http://blog.stevensoroka.ca)
|
146
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "scheduler_daemon"
|
8
|
+
gem.summary = %Q{Rails 3 compatible scheduler daemon. Replaces cron/rake pattern of periodically running rake tasks
|
9
|
+
to perform maintenance tasks in Rails apps. Scheduler Daemon is made specifically for your Rails app,
|
10
|
+
and only loads the environment once, no matter how many tasks run.
|
11
|
+
|
12
|
+
What's so great about it? Well, I'm glad you asked!
|
13
|
+
|
14
|
+
- Only loads your Rails environment once on daemon start, not every time a task is run
|
15
|
+
- Allows you to easily deploy the scheduled tasks with your Rails app instead of depending on an
|
16
|
+
administrator to update crontab
|
17
|
+
- It doesn't use rake or cron!
|
18
|
+
- Gets you up and running with your own daemon in under 2 minutes
|
19
|
+
}
|
20
|
+
gem.version = File.read('VERSION').chomp
|
21
|
+
gem.description = 'a Rails 2.3, Rails 3, and Ruby compatible scheduler daemon. Replaces cron/rake pattern of periodically running rake tasks to perform maintenance tasks, only loading the environment ONCE.'
|
22
|
+
gem.email = "ssoroka78@gmail.com"
|
23
|
+
gem.homepage = "http://github.com/ssoroka/scheduler_daemon"
|
24
|
+
gem.authors = ["Steven Soroka"]
|
25
|
+
gem.add_dependency('eventmachine', '>= 0.12.8')
|
26
|
+
gem.add_dependency('daemons', '>= 1.0.10')
|
27
|
+
gem.add_dependency('rufus-scheduler', '>= 2.0.1')
|
28
|
+
gem.add_dependency('chronic', '>= 0.2.0')
|
29
|
+
|
30
|
+
gem.executables = ['scheduler_daemon']
|
31
|
+
|
32
|
+
everything_from_dirs = %w(bin lib spec)
|
33
|
+
gem.files = everything_from_dirs.map{|d| Dir["#{d}/**/*"] }.flatten
|
34
|
+
gem.files += Dir['*'] - (everything_from_dirs + ['pkg'])
|
35
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
36
|
+
end
|
37
|
+
|
38
|
+
rescue LoadError
|
39
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
40
|
+
end
|
41
|
+
|
42
|
+
# require 'spec/rake/spectask'
|
43
|
+
# Spec::Rake::SpecTask.new(:spec) do |spec|
|
44
|
+
# spec.libs << 'lib' << 'spec'
|
45
|
+
# spec.spec_files = FileList['spec/**/*_spec.rb']
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# Spec::Rake::SpecTask.new(:rcov) do |spec|
|
49
|
+
# spec.libs << 'lib' << 'spec'
|
50
|
+
# spec.pattern = 'spec/**/*_spec.rb'
|
51
|
+
# spec.rcov = true
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# task :default => :spec
|
56
|
+
#
|
57
|
+
# require 'rake/rdoctask'
|
58
|
+
# Rake::RDocTask.new do |rdoc|
|
59
|
+
# if File.exist?('VERSION.yml')
|
60
|
+
# config = YAML.load(File.read('VERSION.yml'))
|
61
|
+
# version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
62
|
+
# else
|
63
|
+
# version = ""
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# rdoc.rdoc_dir = 'rdoc'
|
67
|
+
# rdoc.title = "scheduler_daemon #{version}"
|
68
|
+
# rdoc.rdoc_files.include('README*')
|
69
|
+
# rdoc.rdoc_files.include('lib/**/*.rb')
|
70
|
+
# end
|
71
|
+
#
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.2
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This file launches the scheduler as a daemon.
|
3
|
+
# USAGE:
|
4
|
+
#
|
5
|
+
# scheduler_daemon run # start the daemon and stay on top
|
6
|
+
# scheduler_daemon start # start the daemon and stay on top
|
7
|
+
# scheduler_daemon stop # stop all instances of the application
|
8
|
+
# scheduler_daemon restart # stop all instances and restart them afterwards
|
9
|
+
#
|
10
|
+
# options can be passed to the scheduler like so:
|
11
|
+
#
|
12
|
+
# scheduler_daemon start -- --except=session_cleaner
|
13
|
+
#
|
14
|
+
# options can be passed to the daemon:
|
15
|
+
#
|
16
|
+
# scheduler_daemon start --dir=/my/rails/root/
|
17
|
+
#
|
18
|
+
# see README for more info
|
19
|
+
require 'rubygems'
|
20
|
+
require 'daemons'
|
21
|
+
require 'scheduler_daemon/command_line_args_to_hash'
|
22
|
+
|
23
|
+
# arguments to pass to the daemon launcher
|
24
|
+
def launch_args(options = {})
|
25
|
+
params = options.map{|k,v| "--#{k}=#{v}"}
|
26
|
+
if params.empty?
|
27
|
+
ARGV
|
28
|
+
else
|
29
|
+
args = ARGV.dup
|
30
|
+
args << '--' unless args.include?('--')
|
31
|
+
args + params
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# app arguments
|
36
|
+
app_args = {}
|
37
|
+
# only take args after the '--' arg.
|
38
|
+
if separator_index = ARGV.index('--')
|
39
|
+
app_args = CommandLineArgsToHash.parse(ARGV[separator_index+1..-1])
|
40
|
+
end
|
41
|
+
|
42
|
+
app_args[:dir] ||= Dir.pwd
|
43
|
+
app_args[:pid_dir] ||= File.expand_path(File.join(app_args[:dir], 'log'))
|
44
|
+
scheduler = File.join(File.dirname(__FILE__), %w(.. lib loader scheduler_loader.rb))
|
45
|
+
|
46
|
+
raise "#{pid_dir} does not exist" unless File.exist?(app_args[:pid_dir])
|
47
|
+
|
48
|
+
app_options = {
|
49
|
+
:app_name => 'scheduler_daemon',
|
50
|
+
:ARGV => launch_args(app_args),
|
51
|
+
:dir_mode => :normal,
|
52
|
+
:dir => app_args[:pid_dir],
|
53
|
+
:multiple => false,
|
54
|
+
:backtrace => true,
|
55
|
+
:log_output => true,
|
56
|
+
:monitor => true
|
57
|
+
}
|
58
|
+
|
59
|
+
Daemons.run(scheduler, app_options)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This file loads the rails environment and starts the scheduler.
|
3
|
+
# do not use it directly unless you don't intend for the scheduler to run as a daemon.
|
4
|
+
require 'scheduler_daemon/command_line_args_to_hash'
|
5
|
+
args = CommandLineArgsToHash.parse(ARGV)
|
6
|
+
daemons_lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
7
|
+
|
8
|
+
Dir.chdir(args[:dir])
|
9
|
+
|
10
|
+
require File.join(daemons_lib_dir, 'scheduler_daemon', 'base')
|
11
|
+
|
12
|
+
Scheduler::Base.new(args)
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'rufus/scheduler'
|
3
|
+
begin
|
4
|
+
require 'active_support/hash_with_indifferent_access'
|
5
|
+
rescue LoadError
|
6
|
+
begin
|
7
|
+
require 'active_support/core_ext/hash'
|
8
|
+
rescue LoadError
|
9
|
+
puts "can't load activesupport gem not loaded"
|
10
|
+
raise $!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'scheduler_daemon/scheduler_task'
|
15
|
+
require 'scheduler_daemon/exception_handler'
|
16
|
+
require 'scheduler_daemon/command_line_args_to_hash'
|
17
|
+
|
18
|
+
module Scheduler
|
19
|
+
class Base
|
20
|
+
attr_reader :tasks, :options, :env_name
|
21
|
+
|
22
|
+
# :root_dir is a required option, because the scheduler likely has no idea what the original
|
23
|
+
# root directory was after the process was daemonized (which changes the current directory)
|
24
|
+
# :silent
|
25
|
+
# doesn't output anything to STDOUT or logs.
|
26
|
+
# :root_dir
|
27
|
+
# root dir of the application.
|
28
|
+
# :only
|
29
|
+
# load only tasks in this list
|
30
|
+
# :except
|
31
|
+
# load all tasks except ones in this list
|
32
|
+
# :env_name
|
33
|
+
# if used without rails, you can manually set something in place of the environment name
|
34
|
+
def initialize(opts = {}, command_line_args = [])
|
35
|
+
@options = ::HashWithIndifferentAccess.new(opts)
|
36
|
+
@options.merge!(CommandLineArgsToHash.parse(command_line_args, :array_args => ['only', 'except']))
|
37
|
+
@options['only'] ||= []
|
38
|
+
@options['except'] ||= []
|
39
|
+
@env_name = @options['env_name'] || 'scheduler'
|
40
|
+
@rufus_scheduler = nil
|
41
|
+
@tasks = []
|
42
|
+
|
43
|
+
log("initialized with settings: #{@options.inspect}")
|
44
|
+
|
45
|
+
if !@options['skip_init']
|
46
|
+
load_rails_env
|
47
|
+
load_tasks
|
48
|
+
run_scheduler
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# registers a task class with the scheduler
|
53
|
+
def register_task(task)
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_rails_env
|
58
|
+
if File.exists?('config/environment.rb') && !@options['skip_rails']
|
59
|
+
log("loading rails environment")
|
60
|
+
require File.expand_path('./config/environment')
|
61
|
+
@env_name = ::Rails.env
|
62
|
+
end
|
63
|
+
rescue
|
64
|
+
log("Error loading rails environment; #{$!.class.name}: #{$!.message}")
|
65
|
+
raise $!
|
66
|
+
end
|
67
|
+
|
68
|
+
# time redefines itself with a faster implementation, since it gets called a lot.
|
69
|
+
def time
|
70
|
+
if Time.respond_to?(:zone) && Time.zone
|
71
|
+
self.class.send(:define_method, :time) { Time.zone.now.to_s }
|
72
|
+
else
|
73
|
+
self.class.send(:define_method, :time) { Time.now.to_s }
|
74
|
+
end
|
75
|
+
time
|
76
|
+
end
|
77
|
+
|
78
|
+
def log(*args)
|
79
|
+
return if @options[:silent]
|
80
|
+
Kernel::puts(%([#{time}] #{args.join("\n")}))
|
81
|
+
end
|
82
|
+
alias :puts :log
|
83
|
+
|
84
|
+
def run_scheduler
|
85
|
+
if defined?(::Rails)
|
86
|
+
log "Starting Scheduler in #{::Rails.env}"
|
87
|
+
else
|
88
|
+
log "Starting Scheduler"
|
89
|
+
end
|
90
|
+
|
91
|
+
$daemon_scheduler = self
|
92
|
+
|
93
|
+
EventMachine::run {
|
94
|
+
@rufus_scheduler = Rufus::Scheduler::EmScheduler.start_new
|
95
|
+
|
96
|
+
def @rufus_scheduler.handle_exception(job, exception)
|
97
|
+
msg = "[#{env_name}] scheduler job #{job.job_id} (#{job.tags * ' '}) caught exception #{exception.inspect}"
|
98
|
+
log msg
|
99
|
+
log exception.backtrace.join("\n")
|
100
|
+
Scheduler::ExceptionHandler.handle_exception(exception, job, message)
|
101
|
+
end
|
102
|
+
|
103
|
+
def @rufus_scheduler.daemon_scheduler
|
104
|
+
$daemon_scheduler
|
105
|
+
end
|
106
|
+
|
107
|
+
# This is where the magic happens. tasks in scheduled_tasks/*.rb are loaded up.
|
108
|
+
tasks.each do |task|
|
109
|
+
if task.should_run_in_current_environment?(env_name)
|
110
|
+
task.add_to(@rufus_scheduler)
|
111
|
+
else
|
112
|
+
log "[#{env_name}] #{task} not configured to run; skipping."
|
113
|
+
end
|
114
|
+
end
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def load_tasks
|
119
|
+
tasks_to_run.each{|f|
|
120
|
+
begin
|
121
|
+
unless options[:only].any? && options[:only].all?{|m| f !~ Regexp.new(Regexp.escape(m)) }
|
122
|
+
require File.expand_path("./#{f}")
|
123
|
+
filename = f.split('/').last.split('.').first
|
124
|
+
log "Loading task #{filename}..."
|
125
|
+
@tasks << filename.camelcase.constantize # "path/newsfeed_task.rb" => NewsfeedTask
|
126
|
+
end
|
127
|
+
rescue Exception => e
|
128
|
+
msg = "Error loading task #{filename}: #{e.class.name}: #{e.message}"
|
129
|
+
log msg
|
130
|
+
log e.backtrace.join("\n")
|
131
|
+
Scheduler::ExceptionHandler.handle_exception(e, nil, msg)
|
132
|
+
end
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
def tasks_to_run
|
137
|
+
task_files = Dir[File.join(%w(scheduled_tasks *.rb))]# + File.join(%w(lib scheduled_tasks *.rb))
|
138
|
+
|
139
|
+
if options[:only].any?
|
140
|
+
task_files.reject!{|f| options[:only].all?{|m| f !~ Regexp.new(Regexp.escape(m))}}
|
141
|
+
end
|
142
|
+
|
143
|
+
if options[:except].any?
|
144
|
+
task_files.reject!{|f| options[:except].any?{|m| f =~ Regexp.new(Regexp.escape(m))}}
|
145
|
+
end
|
146
|
+
task_files
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
begin
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
rescue LoadError
|
4
|
+
begin
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
rescue LoadError
|
7
|
+
puts "can't load activesupport gem not loaded"
|
8
|
+
raise $!
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class CommandLineArgsToHash
|
13
|
+
def self.parse(args, options = {})
|
14
|
+
new(args, options).parse
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(args, options = {})
|
18
|
+
@args = args
|
19
|
+
@options = options
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse
|
23
|
+
hash = ::HashWithIndifferentAccess.new
|
24
|
+
@args.each{|arg|
|
25
|
+
k, v = read_argument(arg)
|
26
|
+
hash[k] = v
|
27
|
+
}
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_argument(arg)
|
32
|
+
k, v = arg.sub(/^\-\-/, '').split('=')
|
33
|
+
k = k.gsub(/-/, '_') # replace - to _ so that --skip-init becomes options[:skip_init]
|
34
|
+
v = true if v.nil? # default passed in args to true.
|
35
|
+
v = format_value(k, v)
|
36
|
+
[k, v]
|
37
|
+
end
|
38
|
+
|
39
|
+
def format_value(k, v)
|
40
|
+
if @options[:array_args] && @options[:array_args].include?(k)
|
41
|
+
v = v.split(/,\s*/) if v.respond_to?(:split)
|
42
|
+
end
|
43
|
+
v = false if v == 'false'
|
44
|
+
v = true if v == 'true'
|
45
|
+
v
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# override this in your app to do something meaningful,
|
2
|
+
# like post to campfire or hoptoad.
|
3
|
+
#
|
4
|
+
# Example campfire code below, using 'tinder' gem:
|
5
|
+
module Scheduler
|
6
|
+
class ExceptionHandler
|
7
|
+
# @@campfire_subdomain = ''
|
8
|
+
# @@campfire_username = ''
|
9
|
+
# @@campfire_password = ''
|
10
|
+
# @@campfire_room_name = ''
|
11
|
+
# @@campfire_room = nil
|
12
|
+
|
13
|
+
def self.handle_exception(exception, job, message)
|
14
|
+
# If your team all hangs out in Campfire, you might want to try
|
15
|
+
# something like Tinder here to write these messages out to campfire,
|
16
|
+
# Such as:
|
17
|
+
#
|
18
|
+
# if Rails.env.production? || Rails.env.staging?
|
19
|
+
# msg = "#{message}, see log for backtrace"
|
20
|
+
#
|
21
|
+
# unless @@campfire_room
|
22
|
+
# campfire = Tinder::Campfire.new(@@campfire_subdomain, :ssl => true)
|
23
|
+
# campfire.login(@@campfire_username, @@campfire_password)
|
24
|
+
# @@campfire_room = campfire.find_room_by_name(@@campfire_room_name)
|
25
|
+
# end
|
26
|
+
# @@campfire_room.speak(msg)
|
27
|
+
# end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class SchedulerGenerator < Rails::Generator::Base
|
2
|
+
def banner
|
3
|
+
"Usage: #{$0} #{spec.name}"
|
4
|
+
end
|
5
|
+
|
6
|
+
def manifest
|
7
|
+
record do |m|
|
8
|
+
m.directory File.join('lib', 'scheduled_tasks')
|
9
|
+
|
10
|
+
m.template 'lib/scheduled_tasks/session_cleaner_task.rb',
|
11
|
+
'lib/scheduled_tasks/session_cleaner_task.rb'
|
12
|
+
|
13
|
+
m.readme('README')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class SessionCleanerTask < Scheduler::SchedulerTask
|
2
|
+
environments :all
|
3
|
+
|
4
|
+
every '1d', :first_at => Chronic.parse('next 2 am')
|
5
|
+
|
6
|
+
def run
|
7
|
+
remove_old_sessions
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove_old_sessions
|
11
|
+
log "running the session cleaner"
|
12
|
+
if ActionController::Base.session_store == session_store_class
|
13
|
+
ActiveRecord::Base.connection.execute("DELETE FROM #{session_table_name} WHERE updated_at < '#{7.days.ago.to_s(:db)}'")
|
14
|
+
log "old sessions are gone!"
|
15
|
+
else
|
16
|
+
log "sessions are not stored in the database; nothing to do."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def session_store_class
|
21
|
+
return ActiveRecord::SessionStore if defined?(ActiveRecord::SessionStore)
|
22
|
+
# pre rails 2.3 support...
|
23
|
+
return CGI::Session::ActiveRecordStore if defined?(CGI::Session::ActiveRecordStore)
|
24
|
+
end
|
25
|
+
|
26
|
+
def session_table_name
|
27
|
+
ActiveRecord::Base.pluralize_table_names ? :sessions : :session
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class SchedulerTaskGenerator < Rails::Generators::NamedBase
|
2
|
+
check_class_collision :suffix => 'Task'
|
3
|
+
|
4
|
+
def create_task
|
5
|
+
template File.join(source_dir, 'example_task.rb'), "scheduled_tasks/#{file_name}_task.rb"
|
6
|
+
readme(File.join(template_dir, 'README'))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
File.dirname(File.expand_path(__FILE__))
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def source_dir
|
15
|
+
File.join(template_dir, 'scheduled_tasks')
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_dir
|
19
|
+
File.join(File.dirname(__FILE__), 'templates')
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
Awesome! Now that you've created a scheduler, you can test it out with:
|
3
|
+
|
4
|
+
bundle exec scheduler_daemon run
|
5
|
+
|
6
|
+
to run it in the background (a la system start-up):
|
7
|
+
|
8
|
+
bundle exec scheduler_daemon start
|
9
|
+
|
10
|
+
|
11
|
+
You'll probably want to add tests or specs for your new task.
|
12
|
+
You can find existing specs for scheduler_daemon in the scheduler_daemon/spec folder.
|
13
|
+
|
14
|
+
Be sure to copy them to your spec folder if you're using rspec.
|
data/lib/scheduler_daemon/rails/generators/scheduler_task/templates/scheduled_tasks/example_task.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class <%= class_name %>Task < Scheduler::SchedulerTask
|
2
|
+
environments :all
|
3
|
+
# environments :staging, :production
|
4
|
+
|
5
|
+
every '10s'
|
6
|
+
# other examples:
|
7
|
+
# every '24h', :first_at => Chronic.parse('next midnight')
|
8
|
+
# cron '* 4 * * *' # cron style
|
9
|
+
# in '30s' # run once, 30 seconds from scheduler start/restart
|
10
|
+
|
11
|
+
|
12
|
+
def run
|
13
|
+
# Your code here, eg:
|
14
|
+
# User.send_due_invoices!
|
15
|
+
|
16
|
+
# use log() for writing to scheduler daemon log
|
17
|
+
log("I've sent invoices!")
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Scheduler
|
2
|
+
class SchedulerTask
|
3
|
+
attr_accessor :daemon_scheduler, :rufus_scheduler
|
4
|
+
class <<self
|
5
|
+
def add_to(schedule)
|
6
|
+
%w(every in at cron).each{|time_cmd|
|
7
|
+
if args = self.instance_variable_get("@#{time_cmd}")
|
8
|
+
# add a default tag to the arguments so we know which task was running
|
9
|
+
options = args.extract_options!
|
10
|
+
options.merge!(:tags => [name])
|
11
|
+
args << options
|
12
|
+
|
13
|
+
schedule.send(time_cmd, *args) do
|
14
|
+
begin
|
15
|
+
a_task = new
|
16
|
+
a_task.daemon_scheduler = schedule.daemon_scheduler
|
17
|
+
a_task.rufus_scheduler = schedule
|
18
|
+
a_task.run
|
19
|
+
ensure
|
20
|
+
# Note: AR's ActiveRecord::Base.connection_pool.with_connection(&block) seems broken;
|
21
|
+
# it doesn't release the connection properly.
|
22
|
+
ActiveRecord::Base.connection_pool.release_connection
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# run the task every... '5m', etc. see rufus-scheduler docs
|
30
|
+
def every(*args)
|
31
|
+
@every = args
|
32
|
+
end
|
33
|
+
|
34
|
+
# run the task in '30s', etc. see rufus-scheduler docs
|
35
|
+
def in(*args)
|
36
|
+
@in = args
|
37
|
+
end
|
38
|
+
|
39
|
+
# run the task at... Cronic.parse('5 pm'), etc. see rufus-scheduler docs
|
40
|
+
def at(*args)
|
41
|
+
@at = args
|
42
|
+
end
|
43
|
+
|
44
|
+
# run the task cron '* 4 * * *', etc. see rufus-scheduler docs
|
45
|
+
def cron(*args)
|
46
|
+
@cron = args
|
47
|
+
end
|
48
|
+
|
49
|
+
# what environments should this task run in?
|
50
|
+
# accepts the usual :development, :production, as well as :all
|
51
|
+
#
|
52
|
+
# examples:
|
53
|
+
# environments :all
|
54
|
+
# environments :staging, :production
|
55
|
+
# environments :development
|
56
|
+
#
|
57
|
+
def environments(*args)
|
58
|
+
@environments = args.map{|arg| arg.to_sym }
|
59
|
+
end
|
60
|
+
|
61
|
+
def should_run_in_current_environment?(env)
|
62
|
+
@environments.nil? || @environments == [:all] || @environments.include?(env.to_sym)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# override me to do stuff
|
67
|
+
def run
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def log(*args)
|
72
|
+
daemon_scheduler.log(*args)
|
73
|
+
end
|
74
|
+
alias :puts :log
|
75
|
+
end
|
76
|
+
end
|
77
|
+
# alias this for backwards compatability
|
78
|
+
# SchedulerTask = Scheduler::SchedulerTask unless defined?(::SchedulerTask)
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{scheduler_daemon_robertcigan}
|
8
|
+
s.version = "1.1.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Steven Soroka"]
|
12
|
+
s.date = %q{2013-02-26}
|
13
|
+
s.description = %q{a Rails 2.3, Rails 3, and Ruby compatible scheduler daemon. Replaces cron/rake pattern of periodically running rake tasks to perform maintenance tasks, only loading the environment ONCE.}
|
14
|
+
s.email = %q{ssoroka78@gmail.com}
|
15
|
+
s.executables = ["scheduler_daemon"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README.markdown"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"Gemfile",
|
21
|
+
"Gemfile.lock",
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"bin/scheduler_daemon",
|
27
|
+
"lib/loader/scheduler_loader.rb",
|
28
|
+
"lib/scheduler_daemon.rb",
|
29
|
+
"lib/scheduler_daemon/base.rb",
|
30
|
+
"lib/scheduler_daemon/command_line_args_to_hash.rb",
|
31
|
+
"lib/scheduler_daemon/exception_handler.rb",
|
32
|
+
"lib/scheduler_daemon/rails/generators/scheduler/USAGE",
|
33
|
+
"lib/scheduler_daemon/rails/generators/scheduler/scheduler_generator.rb",
|
34
|
+
"lib/scheduler_daemon/rails/generators/scheduler/templates/README",
|
35
|
+
"lib/scheduler_daemon/rails/generators/scheduler/templates/lib/scheduled_tasks/session_cleaner_task.rb",
|
36
|
+
"lib/scheduler_daemon/rails/generators/scheduler_task/scheduler_task_generator.rb",
|
37
|
+
"lib/scheduler_daemon/rails/generators/scheduler_task/templates/README",
|
38
|
+
"lib/scheduler_daemon/rails/generators/scheduler_task/templates/scheduled_tasks/example_task.rb",
|
39
|
+
"lib/scheduler_daemon/rails/railtie.rb",
|
40
|
+
"lib/scheduler_daemon/scheduler_task.rb",
|
41
|
+
"scheduler_daemon_robertcigan.gemspec",
|
42
|
+
"spec/command_line_args_to_hash_spec.rb",
|
43
|
+
"spec/scheduled_tasks/session_cleaner_task_spec.rb",
|
44
|
+
"spec/scheduler_spec.rb",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
s.homepage = %q{http://github.com/ssoroka/scheduler_daemon}
|
48
|
+
s.require_paths = ["lib"]
|
49
|
+
s.rubygems_version = %q{1.7.2}
|
50
|
+
s.summary = %q{Rails 3 compatible scheduler daemon. Replaces cron/rake pattern of periodically running rake tasks to perform maintenance tasks in Rails apps. Scheduler Daemon is made specifically for your Rails app, and only loads the environment once, no matter how many tasks run. What's so great about it? Well, I'm glad you asked! - Only loads your Rails environment once on daemon start, not every time a task is run - Allows you to easily deploy the scheduled tasks with your Rails app instead of depending on an administrator to update crontab - It doesn't use rake or cron! - Gets you up and running with your own daemon in under 2 minutes}
|
51
|
+
s.test_files = [
|
52
|
+
"spec/command_line_args_to_hash_spec.rb",
|
53
|
+
"spec/scheduled_tasks/session_cleaner_task_spec.rb",
|
54
|
+
"spec/scheduler_spec.rb",
|
55
|
+
"spec/spec_helper.rb"
|
56
|
+
]
|
57
|
+
|
58
|
+
if s.respond_to? :specification_version then
|
59
|
+
s.specification_version = 3
|
60
|
+
|
61
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
62
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.8"])
|
63
|
+
s.add_runtime_dependency(%q<daemons>, [">= 1.0.10"])
|
64
|
+
s.add_runtime_dependency(%q<rufus-scheduler>, [">= 2.0.1"])
|
65
|
+
s.add_runtime_dependency(%q<chronic>, [">= 0.2.0"])
|
66
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<eventmachine>, [">= 0.12.8"])
|
69
|
+
s.add_dependency(%q<daemons>, [">= 1.0.10"])
|
70
|
+
s.add_dependency(%q<rufus-scheduler>, [">= 2.0.1"])
|
71
|
+
s.add_dependency(%q<chronic>, [">= 0.2.0"])
|
72
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
73
|
+
end
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<eventmachine>, [">= 0.12.8"])
|
76
|
+
s.add_dependency(%q<daemons>, [">= 1.0.10"])
|
77
|
+
s.add_dependency(%q<rufus-scheduler>, [">= 2.0.1"])
|
78
|
+
s.add_dependency(%q<chronic>, [">= 0.2.0"])
|
79
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'scheduler_daemon/command_line_args_to_hash'
|
3
|
+
|
4
|
+
describe CommandLineArgsToHash do
|
5
|
+
it 'should process arguments' do
|
6
|
+
h = CommandLineArgsToHash.parse('--hello')
|
7
|
+
h['hello'].should == true
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should change key names with - to _' do
|
11
|
+
h = CommandLineArgsToHash.parse(['--hi-there'])
|
12
|
+
h['hi_there'].should == true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should play nice with array args' do
|
16
|
+
h = CommandLineArgsToHash.parse(['--only=one,two,three'], :array_args => 'only')
|
17
|
+
h['only'].should == %w(one two three)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should handle multiple args ok' do
|
21
|
+
h = CommandLineArgsToHash.parse(['--one', '--two=three'])
|
22
|
+
h['one'].should == true
|
23
|
+
h['two'].should == 'three'
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# copy this spec to your project after installing the plugin if you want to run the specs.
|
2
|
+
# suggested file name for this file: spec/scheduler_daemon/scheduled_tasks/session_cleaner_task_spec.rb
|
3
|
+
|
4
|
+
# require File.join(File.dirname(__FILE__), %w(.. spec_helper))
|
5
|
+
require 'spec_helper'
|
6
|
+
require 'scheduler_daemon/scheduler_task'
|
7
|
+
require 'scheduler_daemon/rails/generators/scheduler/templates/lib/scheduled_tasks/session_cleaner_task'
|
8
|
+
|
9
|
+
describe SessionCleanerTask do
|
10
|
+
before(:each) do
|
11
|
+
@task = SessionCleanerTask.new
|
12
|
+
@task.stub!(:log)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should remove old sessions" do
|
16
|
+
# this test only matters if we're using AR's session store.
|
17
|
+
if defined?(ActionController) && defined?(ActiveRecord) &&
|
18
|
+
ActionController::Base.session_store == ActiveRecord::SessionStore
|
19
|
+
|
20
|
+
# insert old session
|
21
|
+
ActiveRecord::Base.connection.execute(%(delete from #{@task.session_table_name} where session_id = 'abc123'))
|
22
|
+
ActiveRecord::Base.connection.execute(%(insert into #{@task.session_table_name} (session_id, updated_at) values ('abc123', '#{2.years.ago.to_s(:db)}')))
|
23
|
+
|
24
|
+
get_session_count = lambda {
|
25
|
+
ActiveRecord::Base.connection.select_one(%(select count(*) as count from #{@task.session_table_name}))['count'].to_i
|
26
|
+
}
|
27
|
+
|
28
|
+
lambda {
|
29
|
+
@task.run
|
30
|
+
}.should change(get_session_count, :call).by_at_most(-1)
|
31
|
+
else
|
32
|
+
pending 'skipping SessionCleanerTask test since it depends on rails and ActiveRecord::SessionStore; try copying this spec to your rails application.'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'scheduler_daemon/base'
|
3
|
+
|
4
|
+
describe Scheduler::Base do
|
5
|
+
before(:each) do
|
6
|
+
@scheduler = Scheduler::Base.new(:skip_init => true, :silent => true)
|
7
|
+
@scheduler.stub!(:log)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'decide_what_to_run' do
|
11
|
+
it "should support --only" do
|
12
|
+
@scheduler = Scheduler::Base.new({:skip_init => true, :silent => true}, ['--only=alphabets'])
|
13
|
+
@scheduler.options['only'].should == ['alphabets']
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should support --except" do
|
17
|
+
@scheduler = Scheduler::Base.new({:skip_init => true, :silent => true}, ['--except=balloons,monkeys'])
|
18
|
+
@scheduler.options['except'].should == ['balloons', 'monkeys']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
spec_runner = nil
|
3
|
+
begin
|
4
|
+
require 'rspec'
|
5
|
+
spec_runner = RSpec
|
6
|
+
rescue
|
7
|
+
require 'spec'
|
8
|
+
spec_runner = Spec::Runner
|
9
|
+
end
|
10
|
+
require 'chronic'
|
11
|
+
require 'active_support'
|
12
|
+
|
13
|
+
RAILS_ENV = 'test' unless defined?(RAILS_ENV) && RAILS_ENV == 'test'
|
14
|
+
|
15
|
+
spec_runner.configure do |config|
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scheduler_daemon_robertcigan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Steven Soroka
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-26 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: &70144495925840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.12.8
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70144495925840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: daemons
|
27
|
+
requirement: &70144495922360 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.10
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70144495922360
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rufus-scheduler
|
38
|
+
requirement: &70144495919080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.1
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70144495919080
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: chronic
|
49
|
+
requirement: &70144495918340 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70144495918340
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: activesupport
|
60
|
+
requirement: &70144495917540 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70144495917540
|
69
|
+
description: a Rails 2.3, Rails 3, and Ruby compatible scheduler daemon. Replaces
|
70
|
+
cron/rake pattern of periodically running rake tasks to perform maintenance tasks,
|
71
|
+
only loading the environment ONCE.
|
72
|
+
email: ssoroka78@gmail.com
|
73
|
+
executables:
|
74
|
+
- scheduler_daemon
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files:
|
77
|
+
- README.markdown
|
78
|
+
files:
|
79
|
+
- Gemfile
|
80
|
+
- Gemfile.lock
|
81
|
+
- MIT-LICENSE
|
82
|
+
- README.markdown
|
83
|
+
- Rakefile
|
84
|
+
- VERSION
|
85
|
+
- bin/scheduler_daemon
|
86
|
+
- lib/loader/scheduler_loader.rb
|
87
|
+
- lib/scheduler_daemon.rb
|
88
|
+
- lib/scheduler_daemon/base.rb
|
89
|
+
- lib/scheduler_daemon/command_line_args_to_hash.rb
|
90
|
+
- lib/scheduler_daemon/exception_handler.rb
|
91
|
+
- lib/scheduler_daemon/rails/generators/scheduler/USAGE
|
92
|
+
- lib/scheduler_daemon/rails/generators/scheduler/scheduler_generator.rb
|
93
|
+
- lib/scheduler_daemon/rails/generators/scheduler/templates/README
|
94
|
+
- lib/scheduler_daemon/rails/generators/scheduler/templates/lib/scheduled_tasks/session_cleaner_task.rb
|
95
|
+
- lib/scheduler_daemon/rails/generators/scheduler_task/scheduler_task_generator.rb
|
96
|
+
- lib/scheduler_daemon/rails/generators/scheduler_task/templates/README
|
97
|
+
- lib/scheduler_daemon/rails/generators/scheduler_task/templates/scheduled_tasks/example_task.rb
|
98
|
+
- lib/scheduler_daemon/rails/railtie.rb
|
99
|
+
- lib/scheduler_daemon/scheduler_task.rb
|
100
|
+
- scheduler_daemon_robertcigan.gemspec
|
101
|
+
- spec/command_line_args_to_hash_spec.rb
|
102
|
+
- spec/scheduled_tasks/session_cleaner_task_spec.rb
|
103
|
+
- spec/scheduler_spec.rb
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
homepage: http://github.com/ssoroka/scheduler_daemon
|
106
|
+
licenses: []
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 1.8.10
|
126
|
+
signing_key:
|
127
|
+
specification_version: 3
|
128
|
+
summary: Rails 3 compatible scheduler daemon. Replaces cron/rake pattern of periodically
|
129
|
+
running rake tasks to perform maintenance tasks in Rails apps. Scheduler Daemon
|
130
|
+
is made specifically for your Rails app, and only loads the environment once, no
|
131
|
+
matter how many tasks run. What's so great about it? Well, I'm glad you asked! -
|
132
|
+
Only loads your Rails environment once on daemon start, not every time a task is
|
133
|
+
run - Allows you to easily deploy the scheduled tasks with your Rails app instead
|
134
|
+
of depending on an administrator to update crontab - It doesn't use rake or cron!
|
135
|
+
- Gets you up and running with your own daemon in under 2 minutes
|
136
|
+
test_files:
|
137
|
+
- spec/command_line_args_to_hash_spec.rb
|
138
|
+
- spec/scheduled_tasks/session_cleaner_task_spec.rb
|
139
|
+
- spec/scheduler_spec.rb
|
140
|
+
- spec/spec_helper.rb
|