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 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