chrono_trigger 0.1.7 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt DELETED
@@ -1,13 +0,0 @@
1
- == 0.0.4 2009-04-09
2
- * 1 enhancement
3
- * Added chrono_trigger binary and supporting files
4
-
5
- == 0.0.2 2009-04-02
6
-
7
- * 1 minor enhancement:
8
- * Updated to add tasks file
9
-
10
- == 0.0.1 2009-04-02
11
-
12
- * 1 major enhancement:
13
- * Initial release
data/Manifest.txt DELETED
@@ -1,24 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- PostInstall.txt
4
- README.rdoc
5
- Rakefile
6
- bin/chrono_trigger
7
- lib/chrono_trigger.rb
8
- lib/chrono_trigger/cron_entry.rb
9
- lib/chrono_trigger/process.rb
10
- lib/chrono_trigger/runner.rb
11
- lib/chrono_trigger/shell.rb
12
- lib/chrono_trigger/tasks.rb
13
- lib/chrono_trigger/trigger.rb
14
- lib/triggers/test_triggers.rb
15
- script/console
16
- script/destroy
17
- script/generate
18
- tasks/chrono_trigger.rake
19
- test/test_chrono_trigger.rb
20
- test/test_cron_entry.rb
21
- test/test_helper.rb
22
- test/test_shell.rb
23
- test/test_trigger.rb
24
- test/triggers.rb
data/PostInstall.txt DELETED
@@ -1 +0,0 @@
1
-
data/README.rdoc DELETED
@@ -1,59 +0,0 @@
1
- = chrono_trigger
2
-
3
- This is a branch of http://github.com/gregfitz23/chrono_trigger/tree/master as it hasn't been updated in sometime.
4
- New code can be found at https://github.com/darful/chrono_trigger.
5
-
6
- == DESCRIPTION:
7
-
8
- A cron framework for defining cron tasks using a readable DSL.
9
-
10
- == FEATURES/PROBLEMS:
11
-
12
- == SYNOPSIS:
13
-
14
- Create trigger files directory.
15
- Triggers should follow the pattern:
16
-
17
- trigger "name" do
18
- runs { code to execute }
19
- on :monday
20
- every :minutes=>10
21
- at :hour=>9, :minute=>[30,50]
22
- end
23
- Run `chrono_trigger -t{full path to trigger file}`.
24
- Other available options are:
25
- * -a - Specify an application context for the triggers to run against.
26
- * -e - Specify the environment the triggers should run against
27
-
28
- == REQUIREMENTS:
29
-
30
- * ActiveSupport >= 2.0.2
31
-
32
- == INSTALL:
33
-
34
- * sudo gem install chrono_trigger
35
-
36
- == LICENSE:
37
-
38
- (The MIT License)
39
-
40
- Copyright (c) 2009 FIXME full name
41
-
42
- Permission is hereby granted, free of charge, to any person obtaining
43
- a copy of this software and associated documentation files (the
44
- 'Software'), to deal in the Software without restriction, including
45
- without limitation the rights to use, copy, modify, merge, publish,
46
- distribute, sublicense, and/or sell copies of the Software, and to
47
- permit persons to whom the Software is furnished to do so, subject to
48
- the following conditions:
49
-
50
- The above copyright notice and this permission notice shall be
51
- included in all copies or substantial portions of the Software.
52
-
53
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION.yml DELETED
@@ -1,4 +0,0 @@
1
- ---
2
- :major: 0
3
- :minor: 1
4
- :patch: 7
data/bin/chrono_trigger DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
-
4
- require 'chrono_trigger/runner'
5
-
6
- ChronoTrigger::Runner.run
7
-
@@ -1,69 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
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 = "chrono_trigger"
8
- s.version = "0.1.7"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Jon Ciccone"]
12
- s.date = "2012-08-22"
13
- s.description = "Binding to tag"
14
- s.email = "darful@gmail.com"
15
- s.executables = ["chrono_trigger"]
16
- s.extra_rdoc_files = [
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- "History.txt",
21
- "Manifest.txt",
22
- "PostInstall.txt",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION.yml",
26
- "bin/chrono_trigger",
27
- "chrono_trigger.gemspec",
28
- "lib/chrono_trigger.rb",
29
- "lib/chrono_trigger/cron_entry.rb",
30
- "lib/chrono_trigger/process.rb",
31
- "lib/chrono_trigger/runner.rb",
32
- "lib/chrono_trigger/shell.rb",
33
- "lib/chrono_trigger/tasks.rb",
34
- "lib/chrono_trigger/trigger.rb",
35
- "lib/tasks/chrono_trigger.rake",
36
- "lib/triggers/test_triggers.rb",
37
- "script/console",
38
- "script/destroy",
39
- "script/generate",
40
- "test/test_chrono_trigger.rb",
41
- "test/test_cron_entry.rb",
42
- "test/test_helper.rb",
43
- "test/test_shell.rb",
44
- "test/test_trigger.rb",
45
- "test/triggers.rb"
46
- ]
47
- s.homepage = ""
48
- s.rdoc_options = ["--charset=UTF-8"]
49
- s.require_paths = ["lib"]
50
- s.rubygems_version = "1.8.24"
51
- s.summary = "binding to tag"
52
- s.test_files = [
53
- "test/test_chrono_trigger.rb",
54
- "test/test_cron_entry.rb",
55
- "test/test_helper.rb",
56
- "test/test_shell.rb",
57
- "test/test_trigger.rb",
58
- "test/triggers.rb"
59
- ]
60
-
61
- if s.respond_to? :specification_version then
62
- s.specification_version = 3
63
-
64
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
- else
66
- end
67
- else
68
- end
69
- end
@@ -1,71 +0,0 @@
1
- module ChronoTrigger
2
-
3
- class CronEntry
4
-
5
- def initialize(options={})
6
- set_days(options[:days])
7
- set_hours(options[:hours])
8
- set_minutes(options[:minutes])
9
- end
10
-
11
- DAYS_CONVERSION = {
12
- :sunday => 0,
13
- :monday => 1,
14
- :tuesday => 2,
15
- :wednesday => 3,
16
- :thursday => 4,
17
- :friday => 5,
18
- :saturday => 6
19
- }
20
-
21
- CALENDAR_DAYS = *(1..31)
22
-
23
- def set_hours(*args)
24
- args.compact!
25
- args.flatten!
26
- raise ChronoTrigger::ConfigurationException.new("Hours must be less than 24") if args.any? {|hour| hour >= 24}
27
- @hours = args
28
- end
29
-
30
- def set_days(*args)
31
- args.compact!
32
- args.flatten!
33
- args.each {|day| raise ChronoTrigger::ConfigurationException.new("Day #{day} setting is invalid") if !DAYS_CONVERSION.keys.include?(day)}
34
- @days = args.map { |day| DAYS_CONVERSION[day] }
35
- end
36
-
37
- def set_minutes(*args)
38
- args.compact!
39
- args.flatten!
40
- raise ChronoTrigger::ConfigurationException.new("Minutes must be less than 60") if args.any? {|minute| minute >= 60}
41
- @minutes = args
42
- end
43
-
44
- def set_calendar_days(*args)
45
- args.compact!
46
- args.flatten!
47
- args.each {|calendar_day| raise ChronoTrigger::ConfigurationException.new("Calendar Day #{calendar_day} setting is invalid") if !CALENDAR_DAYS.include?(calendar_day)}
48
- @calendar_days = args
49
- end
50
-
51
- def matches?(datetime)
52
- if @minutes.blank? && !@days.blank?
53
- raise ChronoTrigger::ConfigurationException.new("Days were specified for a CronEntry with no minutes specified")
54
- end
55
-
56
- if (@minutes.blank? || @hours.blank?) && !@calendar_days.blank?
57
- raise ChronoTrigger::ConfigurationException.new("Calendar Days were specified for a CronEntry with no minutes and/or no hours specified")
58
- end
59
-
60
- if !@days.blank? && !@calendar_days.blank?
61
- raise ChronoTrigger::ConfigurationException.new("Calendar Days and Days were specified. This is unsupported.")
62
- end
63
-
64
- return false if !@minutes.blank? && !@minutes.include?(datetime.min)
65
- return false if !@hours.blank? && !@hours.include?(datetime.hour)
66
- return false if (!@days.blank? && !@days.include?(datetime.wday)) || (!@calendar_days.blank? && !@calendar_days.include?(datetime.day))
67
- return true
68
- end
69
-
70
- end
71
- end
@@ -1,37 +0,0 @@
1
- module ChronoTrigger
2
-
3
- class Process
4
-
5
- def run(options={})
6
- @t = Thread.new do
7
- setup(options)
8
-
9
- shell = ChronoTrigger::Shell.new
10
- options[:trigger_files] ? shell.load_triggers(options[:trigger_files].split(":")) : shell.load_triggers
11
- loop do
12
- shell.execute_triggers
13
- sleep 1.minute.to_i
14
- end
15
- end
16
-
17
- @t.join
18
- end
19
-
20
- def stop
21
- @t.exit
22
- end
23
-
24
- private
25
- def setup(options={})
26
- if application_context = options[:application_context]
27
- ENV['RAILS_ENV'] = options[:env] || "development"
28
-
29
- application_path = File.join(application_context, 'config', 'environment')
30
- STDOUT.puts "Loading application environment at #{File.join(application_context, 'config', 'environment')} for '#{ENV['RAILS_ENV']}' enviroment."
31
- require(application_path)
32
- end
33
-
34
- require "chrono_trigger"
35
- end
36
- end
37
- end
@@ -1,292 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'process')
2
- require "logger"
3
- require 'optparse'
4
- require 'yaml'
5
-
6
- module ChronoTrigger
7
- class Runner
8
-
9
- attr_accessor :options
10
- private :options, :options=
11
-
12
- def self.run
13
- new
14
- end
15
-
16
- def self.shutdown
17
- @@instance.shutdown
18
- end
19
-
20
- def initialize
21
- @@instance = self
22
- parse_options
23
-
24
- @process = ProcessHelper.new(options[:logger], options[:pid_file], options[:user], options[:group])
25
-
26
- if options[:stop]
27
- @process.kill
28
- exit(1)
29
- end
30
-
31
- pid = @process.running?
32
- if pid
33
- if options[:force]
34
- STDOUT.puts "Shutting down existing ChronoTrigger."
35
- @process.kill
36
- @process = ProcessHelper.new(options[:logger], options[:pid_file], options[:user], options[:group])
37
- else
38
- STDERR.puts "There is already a ChronoTrigger process running (pid #{pid}), exiting."
39
- exit(1)
40
- end
41
- elsif pid.nil?
42
- STDERR.puts "Cleaning up stale pidfile at #{options[:pid_file]}."
43
- end
44
-
45
- start
46
- end
47
-
48
- def parse_options
49
- self.options = {
50
- :log_level => Logger::INFO,
51
- :daemonize => false,
52
- :pid_file => File.join('', 'var', 'run', 'chrono_trigger.pid'),
53
- :env => "development"
54
- }
55
-
56
- OptionParser.new do |opts|
57
- opts.summary_width = 25
58
-
59
- opts.banner = "ChronoTrigger - Execute cron jobs within the context of a Rails application\n\n",
60
- "usage: chrono_trigger [options...]\n",
61
- " chrono_trigger --help\n",
62
- " chrono_trigger --version\n"
63
-
64
- opts.separator ""
65
- opts.separator ""; opts.separator "ChronoTrigger Options:"
66
-
67
- opts.on("-tTRIGGER_FILES", "--triggers TRIGGER_FILES", "Path to file(s) specifying triggers to be executed. Multiple files should be separated by a :. When also specifying -a, this path will be relative to the application path") do |trigger_files|
68
- options[:trigger_files] = trigger_files
69
- end
70
-
71
- opts.on("-f", "--force", "Force restart of ChronoTrigger process (can be used in conjunction with -P).") do
72
- options[:force] = true
73
- end
74
-
75
- opts.on("-s", "--stop", "Stop a currently running ChronoTrigger process (can be used in conjunction with -P).") do
76
- options[:stop] = true
77
- end
78
-
79
- opts.separator ""
80
- opts.separator ""; opts.separator "Rails options:"
81
-
82
- opts.on("-aAPPLICATION", "--application RAILS", "Path to Rails application context to execture triggers in.") do |application_context|
83
- options[:application_context] = application_context
84
- end
85
-
86
- opts.on("-eENVIRONMENT", "--environment ENVIRONMENT", "Rails environment to execute triggers in.") do |environment|
87
- options[:env] = environment
88
- end
89
-
90
- opts.separator ""
91
- opts.separator ""; opts.separator "Process:"
92
-
93
- opts.on("-PFILE", "--pid FILENAME", "save PID in FILENAME when using -d option.", "(default: #{options[:pid_file]})") do |pid_file|
94
- options[:pid_file] = File.expand_path(pid_file)
95
- end
96
-
97
- opts.on("-u", "--user USER", "User to run as") do |user|
98
- options[:user] = user.to_i == 0 ? Etc.getpwnam(user).uid : user.to_i
99
- end
100
-
101
- opts.on("-gGROUP", "--group GROUP", "Group to run as") do |group|
102
- options[:group] = group.to_i == 0 ? Etc.getgrnam(group).gid : group.to_i
103
- end
104
-
105
- opts.separator ""; opts.separator "Logging:"
106
-
107
- opts.on("-L", "--log [FILE]", "Path to print debugging information.") do |log_path|
108
- options[:logger] = File.expand_path(log_path)
109
- end
110
-
111
- opts.on("-v", "Increase logging verbosity (may be used multiple times).") do
112
- options[:log_level] -= 1
113
- end
114
-
115
- opts.on("-d", "Run as a daemon.") do
116
- options[:daemonize] = true
117
- end
118
- end.parse!
119
- end
120
-
121
- def start
122
- drop_privileges
123
-
124
- @process.daemonize if options[:daemonize]
125
-
126
- if application_context = options[:application_context]
127
- Dir.chdir(application_context)
128
- end
129
-
130
- setup_signal_traps
131
- @process.write_pid_file
132
-
133
- STDOUT.puts "Starting ChronoTrigger."
134
- @chrono_trigger_process = ChronoTrigger::Process.new
135
- @chrono_trigger_process.run(options)
136
-
137
- @process.remove_pid_file
138
- end
139
-
140
- def drop_privileges
141
- ::Process.egid = options[:group] if options[:group]
142
- ::Process.euid = options[:user] if options[:user]
143
- end
144
-
145
- def shutdown
146
- begin
147
- STDOUT.puts "Shutting down."
148
- @chrono_trigger_process.stop
149
- exit(1)
150
- rescue Object => e
151
- STDERR.puts "There was an error shutting down: #{e}"
152
- exit(70)
153
- end
154
- end
155
-
156
- def setup_signal_traps
157
- Signal.trap("INT") { shutdown }
158
- Signal.trap("TERM") { shutdown }
159
- end
160
- end
161
-
162
- class ProcessHelper
163
-
164
- def initialize(log_file = nil, pid_file = nil, user = nil, group = nil)
165
- @log_file = log_file
166
- @pid_file = pid_file
167
- @user = user
168
- @group = group
169
- end
170
-
171
- def safefork
172
- begin
173
- if pid = fork
174
- return pid
175
- end
176
- rescue Errno::EWOULDBLOCK
177
- sleep 5
178
- retry
179
- end
180
- end
181
-
182
- def daemonize
183
- sess_id = detach_from_terminal
184
- exit if pid = safefork
185
-
186
- Dir.chdir("/")
187
- File.umask 0000
188
-
189
- close_io_handles
190
- redirect_io
191
-
192
- return sess_id
193
- end
194
-
195
- def detach_from_terminal
196
- srand
197
- safefork and exit
198
-
199
- unless sess_id = ::Process.setsid
200
- raise "Couldn't detach from controlling terminal."
201
- end
202
-
203
- trap 'SIGHUP', 'IGNORE'
204
-
205
- sess_id
206
- end
207
-
208
- def close_io_handles
209
- ObjectSpace.each_object(IO) do |io|
210
- unless [STDIN, STDOUT, STDERR].include?(io)
211
- begin
212
- io.close unless io.closed?
213
- rescue Exception
214
- end
215
- end
216
- end
217
- end
218
-
219
- def redirect_io
220
- begin; STDIN.reopen('/dev/null'); rescue Exception; end
221
-
222
- if @log_file
223
- begin
224
- STDOUT.reopen(@log_file, "a")
225
- STDOUT.sync = true
226
- rescue Exception
227
- begin; STDOUT.reopen('/dev/null'); rescue Exception; end
228
- end
229
- else
230
- begin; STDOUT.reopen('/dev/null'); rescue Exception; end
231
- end
232
-
233
- begin; STDERR.reopen(STDOUT); rescue Exception; end
234
- STDERR.sync = true
235
- end
236
-
237
- def rescue_exception
238
- begin
239
- yield
240
- rescue Exception
241
- end
242
- end
243
-
244
- def write_pid_file
245
- return unless @pid_file
246
- FileUtils.mkdir_p(File.dirname(@pid_file))
247
- File.open(@pid_file, "w") { |f| f.write(::Process.pid) }
248
- File.chmod(0644, @pid_file)
249
- end
250
-
251
- def remove_pid_file
252
- return unless @pid_file
253
- File.unlink(@pid_file) if File.exists?(@pid_file)
254
- end
255
-
256
- def running?
257
- return false unless @pid_file
258
-
259
- pid = File.read(@pid_file).chomp.to_i rescue nil
260
- pid = nil if pid == 0
261
- return false unless pid
262
-
263
- begin
264
- ::Process.kill(0, pid)
265
- return pid
266
- rescue Errno::ESRCH
267
- return nil
268
- rescue Errno::EPERM
269
- return pid
270
- end
271
- end
272
-
273
- def kill
274
- return false unless @pid_file
275
-
276
- pid = File.read(@pid_file).chomp.to_i rescue nil
277
- pid = nil if pid == 0
278
- return false unless pid
279
-
280
- begin
281
- ::Process.kill("TERM", pid)
282
- remove_pid_file
283
- return pid
284
- rescue Errno::ESRCH
285
- return nil
286
- rescue Errno::EPERM
287
- return pid
288
- end
289
-
290
- end
291
- end
292
- end