foreverb 0.3.0.a → 0.3.0.b

Sign up to get free protection for your applications and to get access to all the features.
data/lib/forever.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'yaml' unless defined?(YAML)
2
2
  require 'forever/extensions'
3
- require 'forever/every'
3
+ require 'forever/job'
4
4
  require 'forever/base'
5
5
  require 'forever/version'
6
6
 
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
- Dir.chdir(dir) if exists?(dir)
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
- if forking
86
- begin
87
- jobs.select { |job| job.time?(Time.now) }.each do |job|
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
- rescue Errno::EAGAIN
91
- puts "\n\nWait all processes since os cannot create a new one\n\n"
92
- Process.waitall
100
+ else
101
+ Thread.new { job_call(job) }
93
102
  end
94
- else
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(dir, "tmp/#{name}.pid") if exists?(dir, file)
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(dir, 'stop.txt')
328
+ @_stop_txt ||= File.join(tmp, 'stop.txt')
286
329
  end
287
330
  end # Base
288
331
  end # Forever
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Forever
2
- VERSION = "0.3.0.a" unless defined?(Forever::VERSION)
2
+ VERSION = "0.3.0.b" unless defined?(Forever::VERSION)
3
3
  end
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: 50
4
+ hash: 51
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
9
  - 0
10
- - a
11
- version: 0.3.0.a
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-04 00:00:00 +02:00
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