foreverb 0.3.0.a → 0.3.0.b
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/lib/forever.rb +1 -1
- data/lib/forever/base.rb +62 -19
- data/lib/forever/job.rb +50 -0
- data/lib/forever/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +5 -6
- data/lib/forever/every.rb +0 -59
data/lib/forever.rb
CHANGED
data/lib/forever/base.rb
CHANGED
@@ -3,7 +3,6 @@ require 'fileutils'
|
|
3
3
|
module Forever
|
4
4
|
|
5
5
|
class Base
|
6
|
-
include Every
|
7
6
|
attr_reader :started_at
|
8
7
|
|
9
8
|
def initialize(options={}, &block)
|
@@ -16,9 +15,11 @@ module Forever
|
|
16
15
|
|
17
16
|
raise 'No jobs defined!' if jobs.empty?
|
18
17
|
|
19
|
-
|
18
|
+
# Setup directories
|
19
|
+
Dir.chdir(dir)
|
20
|
+
FileUtils.rm_rf(tmp) if File.exist?(tmp)
|
21
|
+
Dir.mkdir(tmp)
|
20
22
|
Dir.mkdir(File.dirname(log)) if log && !File.exist?(File.dirname(log))
|
21
|
-
Dir.mkdir(File.dirname(pid)) if pid && !File.exist?(File.dirname(pid))
|
22
23
|
|
23
24
|
write_config!
|
24
25
|
|
@@ -82,32 +83,56 @@ module Forever
|
|
82
83
|
|
83
84
|
# Start deamons
|
84
85
|
until stopping?
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
current_queue = 1
|
87
|
+
jobs.select { |job| job.time?(Time.now) }.each do |job|
|
88
|
+
if queue && queue > current_queue
|
89
|
+
puts "\n\nThe queue limit has been exceeded\n\n"
|
90
|
+
sleep 60
|
91
|
+
break
|
92
|
+
end
|
93
|
+
if forking
|
94
|
+
begin
|
88
95
|
Process.fork { job_call(job) }
|
96
|
+
rescue Errno::EAGAIN
|
97
|
+
puts "\n\nWait all processes since os cannot create a new one\n\n"
|
98
|
+
Process.waitall
|
89
99
|
end
|
90
|
-
|
91
|
-
|
92
|
-
Process.waitall
|
100
|
+
else
|
101
|
+
Thread.new { job_call(job) }
|
93
102
|
end
|
94
|
-
|
95
|
-
jobs.each { |job| Thread.new { job_call(job) } if job.time?(Time.now) }
|
103
|
+
current_queue += 1
|
96
104
|
end
|
97
|
-
sleep 0.5
|
98
105
|
end
|
99
106
|
|
100
|
-
# If we are here it means we are exiting so we can remove the pid and pending stop.txt
|
101
|
-
FileUtils.rm_f(pid)
|
102
|
-
FileUtils.rm_f(stop_txt)
|
103
|
-
|
104
107
|
# Invoke our after :all filters
|
105
108
|
after_filters[:all].each { |block| safe_call(block) }
|
109
|
+
|
110
|
+
# If we are here it means we are exiting so we can remove the pid and pending stop.txt
|
111
|
+
FileUtils.rm_rf(tmp)
|
106
112
|
end
|
107
113
|
|
108
114
|
self
|
109
115
|
end
|
110
116
|
|
117
|
+
##
|
118
|
+
# Define a new job task
|
119
|
+
#
|
120
|
+
# Example:
|
121
|
+
# every 1.second, :at => '12:00' do
|
122
|
+
# my_long_task
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
def every(period, options={}, &block)
|
126
|
+
jobs << Forever::Job.new(period, options.merge!(:dir => dir), &block)
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Our job list
|
131
|
+
#
|
132
|
+
def jobs
|
133
|
+
@_jobs ||= []
|
134
|
+
end
|
135
|
+
|
111
136
|
##
|
112
137
|
# Caller file
|
113
138
|
#
|
@@ -122,12 +147,27 @@ module Forever
|
|
122
147
|
File.basename(file, '.*')
|
123
148
|
end
|
124
149
|
|
150
|
+
##
|
151
|
+
# Queue size
|
152
|
+
#
|
153
|
+
def queue(value=nil)
|
154
|
+
value ? @_queue = value : @_queue
|
155
|
+
end
|
156
|
+
|
125
157
|
##
|
126
158
|
# Base working Directory
|
127
159
|
#
|
128
160
|
def dir(value=nil)
|
129
161
|
value ? @_dir = value : @_dir
|
130
162
|
end
|
163
|
+
alias :workspace :dir
|
164
|
+
|
165
|
+
##
|
166
|
+
# Temp directory, used to store pids and jobs status
|
167
|
+
#
|
168
|
+
def tmp
|
169
|
+
File.join(dir, 'tmp')
|
170
|
+
end
|
131
171
|
|
132
172
|
##
|
133
173
|
# File were we redirect STOUT and STDERR, can be false.
|
@@ -145,7 +185,7 @@ module Forever
|
|
145
185
|
# Default: dir + 'tmp/[process_name].pid'
|
146
186
|
#
|
147
187
|
def pid(value=nil)
|
148
|
-
@_pid ||= File.join(
|
188
|
+
@_pid ||= File.join(tmp, "#{name}.pid") if exists?(dir, file)
|
149
189
|
value.nil? ? @_pid : @_pid = value
|
150
190
|
end
|
151
191
|
|
@@ -156,9 +196,9 @@ module Forever
|
|
156
196
|
FileUtils.rm_f(stop_txt)
|
157
197
|
if running?
|
158
198
|
pid_was = File.read(pid).to_i
|
159
|
-
FileUtils.rm_f(pid)
|
160
199
|
print "[\e[90m%s\e[0m] Killing process \e[1m%d\e[0m...\n" % [name, pid_was]
|
161
200
|
after_filters[:all].each { |block| safe_call(block) }
|
201
|
+
FileUtils.rm_rf(tmp)
|
162
202
|
Process.kill(:KILL, pid_was)
|
163
203
|
else
|
164
204
|
print "[\e[90m%s\e[0m] Process with \e[1mnot found\e[0m" % name
|
@@ -267,9 +307,12 @@ module Forever
|
|
267
307
|
|
268
308
|
def job_call(job)
|
269
309
|
return unless job.time?(Time.now)
|
310
|
+
job.run!
|
270
311
|
before_filters[:each].each { |block| safe_call(block) }
|
271
312
|
safe_call(job)
|
272
313
|
after_filters[:each].each { |block| safe_call(block) }
|
314
|
+
ensure
|
315
|
+
job.stop!
|
273
316
|
end
|
274
317
|
|
275
318
|
def safe_call(block)
|
@@ -282,7 +325,7 @@ module Forever
|
|
282
325
|
end
|
283
326
|
|
284
327
|
def stop_txt
|
285
|
-
@_stop_txt ||= File.join(
|
328
|
+
@_stop_txt ||= File.join(tmp, 'stop.txt')
|
286
329
|
end
|
287
330
|
end # Base
|
288
331
|
end # Forever
|
data/lib/forever/job.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Forever
|
2
|
+
class Job
|
3
|
+
|
4
|
+
def initialize(period, options, &block)
|
5
|
+
@period = period
|
6
|
+
@at = options[:at] ? parse_at(*options[:at]) : []
|
7
|
+
@pid = File.join(options[:dir], "/tmp/#{object_id}.job")
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
@block.call
|
13
|
+
end
|
14
|
+
|
15
|
+
def run!
|
16
|
+
File.open(@pid, 'w') { |f| f.write('running') }
|
17
|
+
end
|
18
|
+
|
19
|
+
def stop!
|
20
|
+
File.open(@pid, 'w') { |f| f.write('idle') }
|
21
|
+
end
|
22
|
+
|
23
|
+
def running?
|
24
|
+
File.exist?(@pid) && File.read(@pid) == 'running'
|
25
|
+
end
|
26
|
+
|
27
|
+
def last
|
28
|
+
File.mtime(@pid)
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
0
|
31
|
+
end
|
32
|
+
|
33
|
+
def time?(t)
|
34
|
+
elapsed_ready = (t - last).to_i >= @period
|
35
|
+
time_ready = @at.empty? || @at.any? { |at| (at[0].empty? || t.hour == at[0].to_i) && (at[1].empty? || t.min == at[1].to_i) }
|
36
|
+
!running? && elapsed_ready && time_ready
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def parse_at(*args)
|
41
|
+
args.map do |at|
|
42
|
+
raise "#{at} must be a string" unless at.is_a?(String)
|
43
|
+
raise "#{at} has not a colon separator" unless at =~ /:/
|
44
|
+
hour, min = at.split(":")
|
45
|
+
raise "Failed to parse #{at}" if hour.to_i >= 24 || min.to_i >= 60
|
46
|
+
[hour, min]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # Job
|
50
|
+
end # Forever
|
data/lib/forever/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -28,7 +28,7 @@ class MiniTest::Spec
|
|
28
28
|
if @forever
|
29
29
|
capture_io { @forever.stop! }
|
30
30
|
FileUtils.rm_rf(File.dirname(@forever.log)) if @forever.log
|
31
|
-
FileUtils.rm_rf(File.dirname(@forever.pid)) if @forever.pid
|
31
|
+
FileUtils.rm_rf(File.dirname(@forever.pid)) if @forever.pid # this is deleted by Forever
|
32
32
|
end
|
33
33
|
Dir.chdir($dir)
|
34
34
|
ARGV.clear
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreverb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
9
|
- 0
|
10
|
-
-
|
11
|
-
version: 0.3.0.
|
10
|
+
- b
|
11
|
+
version: 0.3.0.b
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- DAddYE
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-10-
|
19
|
+
date: 2011-10-05 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -68,12 +68,11 @@ files:
|
|
68
68
|
- examples/complex
|
69
69
|
- examples/simple
|
70
70
|
- examples/stress
|
71
|
-
- examples/tmp/complex.pid
|
72
71
|
- foreverb.gemspec
|
73
72
|
- lib/forever.rb
|
74
73
|
- lib/forever/base.rb
|
75
|
-
- lib/forever/every.rb
|
76
74
|
- lib/forever/extensions.rb
|
75
|
+
- lib/forever/job.rb
|
77
76
|
- lib/forever/version.rb
|
78
77
|
- spec/cli_spec.rb
|
79
78
|
- spec/foreverb_spec.rb
|
data/lib/forever/every.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
|
3
|
-
module Forever
|
4
|
-
module Every
|
5
|
-
class Job
|
6
|
-
|
7
|
-
def initialize(period, options, block)
|
8
|
-
@period = period
|
9
|
-
@at_start = options[:at] == :start && options.delete(:at) ? true : false
|
10
|
-
@at = options[:at] ? parse_at(*options[:at]) : []
|
11
|
-
@tmp = File.join(Dir.tmpdir, '%x' % rand(255**10))
|
12
|
-
@block = block
|
13
|
-
end
|
14
|
-
|
15
|
-
def call
|
16
|
-
File.open(@tmp, 'w') { |f| f.write('running') }
|
17
|
-
FileUtils.touch(@tmp)
|
18
|
-
@block.call
|
19
|
-
ensure
|
20
|
-
File.open(@tmp, 'w') { |f| f.write('idle') }
|
21
|
-
end
|
22
|
-
|
23
|
-
def running?
|
24
|
-
File.exist?(@tmp) && File.read(@tmp) == 'running'
|
25
|
-
end
|
26
|
-
|
27
|
-
def last
|
28
|
-
File.mtime(@tmp)
|
29
|
-
rescue Errno::ENOENT
|
30
|
-
0
|
31
|
-
end
|
32
|
-
|
33
|
-
def time?(t)
|
34
|
-
elapsed_ready = (t - last).to_i >= @period
|
35
|
-
time_ready = @at.empty? || @at.any? { |at| (at[0].empty? || t.hour == at[0].to_i) && (at[1].empty? || t.min == at[1].to_i) }
|
36
|
-
!running? && elapsed_ready && time_ready
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
def parse_at(*args)
|
41
|
-
args.map do |at|
|
42
|
-
raise "#{at} must be a string" unless at.is_a?(String)
|
43
|
-
raise "#{at} has not a colon separator" unless at =~ /:/
|
44
|
-
hour, min = at.split(":")
|
45
|
-
raise "Failed to parse #{at}" if hour.to_i >= 24 || min.to_i >= 60
|
46
|
-
[hour, min]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end # Job
|
50
|
-
|
51
|
-
def every(period, options={}, &block)
|
52
|
-
jobs << Job.new(period, options, block)
|
53
|
-
end
|
54
|
-
|
55
|
-
def jobs
|
56
|
-
@_jobs ||= []
|
57
|
-
end
|
58
|
-
end # Every
|
59
|
-
end # Forever
|