chrono_trigger 0.1.7 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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