workforce 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/TODO.md ADDED
@@ -0,0 +1,4 @@
1
+ = TODO
2
+
3
+ * Define specialized type of workers such as Queue-based and Timed-based.
4
+ * Implement proper restarting/reloading for smoother deploys.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.4
1
+ 0.3.0
@@ -6,7 +6,7 @@ require "workforce"
6
6
  config = Workforce::Config.instance
7
7
 
8
8
  optparser = OptionParser.new do |opts|
9
- opts.banner = "Usage: #{$0} [options] #{Workforce::Controller::ACTIONS.join("|")} [WORKER]"
9
+ opts.banner = "Usage: #{$0} [options] #{Workforce::Controller::ACTIONS.join("|")} [WORKER]*"
10
10
 
11
11
  opts.separator ""
12
12
  opts.separator "Options:"
@@ -27,6 +27,10 @@ optparser = OptionParser.new do |opts|
27
27
  config.log_dir = log_dir
28
28
  end
29
29
 
30
+ opts.on("-s", "--schedule WORKER:NUM", "Automatically schedule NUM instance of WORKER on start") do |arg|
31
+ config.schedule(*arg.split(/:/))
32
+ end
33
+
30
34
  opts.on("-h", "--help", "Show this screen") do
31
35
  puts optparser
32
36
  exit
@@ -24,6 +24,7 @@ module Workforce
24
24
  yield self if block_given?
25
25
  @before_callbacks = Hash.new { |h,k| h[k] = [] }
26
26
  @after_callbacks = Hash.new { |h,k| h[k] = [] }
27
+ @num_instances = Hash.new { |h,k| h[k] = 0 }
27
28
  end
28
29
 
29
30
  def load_file(file_path)
@@ -32,17 +33,25 @@ module Workforce
32
33
 
33
34
  def before(event, &block)
34
35
  if block_given?
35
- @before_callbacks[event] << block
36
+ @before_callbacks[event.to_sym] << block
36
37
  else
37
- @before_callbacks[event]
38
+ @before_callbacks[event.to_sym]
38
39
  end
39
40
  end
40
41
 
41
42
  def after(event, &block)
42
43
  if block_given?
43
- @after_callbacks[event] << block
44
+ @after_callbacks[event.to_sym] << block
44
45
  else
45
- @after_callbacks[event]
46
+ @after_callbacks[event.to_sym]
47
+ end
48
+ end
49
+
50
+ def schedule(worker, number = nil)
51
+ if number
52
+ @num_instances[worker.to_sym] = Integer(number)
53
+ else
54
+ @num_instances[worker.to_sym]
46
55
  end
47
56
  end
48
57
 
@@ -16,78 +16,90 @@ module Workforce
16
16
 
17
17
  def list
18
18
  puts "Available workers:"
19
- Dir["#{Config.get(:workers_dir)}/*"].each do |file|
20
- worker_name = Inflector.camelcase(File.basename(file, ".rb"))
21
- puts " * #{worker_name}"
22
- end
23
- end
24
-
25
- def run(worker_klass)
26
- if running?(worker_klass)
27
- puts "#{worker_klass}'s manager already running"
28
- exit(1)
29
- end
30
19
 
31
- run_callbacks(:start) do
32
- manager = Workforce::Manager.new(get_klass(worker_klass))
33
- store_pid(worker_klass, Process.pid)
34
- manager.run
35
- remove_pid_file(worker_klass)
20
+ available_workers.each do |worker|
21
+ puts " * #{worker}"
36
22
  end
37
23
  end
38
24
 
39
- def status(worker_klass)
40
- if running?(worker_klass)
41
- puts "Running (#{running_pid(worker_klass)})"
42
- else
43
- puts "Not running"
25
+ def run(*workers)
26
+ perform_action(:start, workers) do |worker_klass|
27
+ if running?(worker_klass)
28
+ puts "#{worker_klass}'s manager already running"
29
+ else
30
+ manager = Workforce::Manager.new(worker_klass)
31
+ store_pid(worker_klass, Process.pid)
32
+ manager.run
33
+ remove_pid_file(worker_klass)
34
+ end
44
35
  end
45
36
  end
46
-
47
- def start(worker_klass)
48
- if running?(worker_klass)
49
- puts "#{worker_klass}'s manager already running"
50
- exit(1)
51
- end
52
-
53
- run_callbacks(:start) do
54
- manager = Workforce::Manager.new(get_klass(worker_klass))
55
- store_pid(worker_klass, manager.launch)
37
+
38
+ def start(*workers)
39
+ perform_action(:start, workers) do |worker_klass|
40
+ if running?(worker_klass)
41
+ puts "#{worker_klass}'s manager already running"
42
+ else
43
+ puts "Starting #{worker_klass}"
44
+ manager = Workforce::Manager.new(worker_klass)
45
+ store_pid(worker_klass, manager.launch)
46
+ num = Config.instance.schedule(worker_klass.name)
47
+ puts "Scheduling #{num} instances"
48
+ num.times { sleep 0.005; schedule(worker_klass) }
49
+ end
56
50
  end
57
51
  end
58
52
 
59
- def stop(worker_klass)
60
- run_callbacks(:stop) do
61
- Process.kill(:QUIT, running_pid(worker_klass))
62
- remove_pid_file(worker_klass)
53
+ def stop(*workers)
54
+ perform_action(:stop, workers) do |worker_klass|
55
+ if running?(worker_klass)
56
+ puts "Stopping #{worker_klass}"
57
+ begin
58
+ Process.kill(:QUIT, running_pid(worker_klass))
59
+ rescue Errno::ESRCH
60
+ end
61
+ remove_pid_file(worker_klass)
62
+ else
63
+ puts "#{worker_klass} is not running"
64
+ end
63
65
  end
64
66
  end
65
67
 
66
- def restart(worker_klass)
67
- run_callbacks(:restart) do
68
+ def restart(*workers)
69
+ perform_action(:restart, workers) do |worker_klass|
68
70
  stop(worker_klass) if running?(worker_klass)
69
71
  start(worker_klass)
70
72
  end
71
73
  end
72
74
 
73
- def schedule(worker_klass)
74
- unless running?(worker_klass)
75
- puts "#{worker_klass}'s manager not running yet"
76
- exit(1)
77
- end
78
-
79
- run_callbacks(:schedule) do
80
- Process.kill(:USR1, running_pid(worker_klass))
75
+ def status(*workers)
76
+ perform_action(:status, workers) do |worker_klass|
77
+ if running?(worker_klass)
78
+ puts "#{worker_klass}: Running (#{running_pid(worker_klass)})"
79
+ else
80
+ puts "#{worker_klass}: Not running"
81
+ end
81
82
  end
82
83
  end
83
84
 
84
- def dispose(worker_klass)
85
- unless running?(worker_klass)
86
- puts "#{worker_klass}'s manager not running yet"
87
- exit(1)
85
+ def schedule(*workers)
86
+ perform_action(:schedule, workers) do |worker_klass|
87
+ unless running?(worker_klass)
88
+ puts "#{worker_klass}'s manager not running yet"
89
+ else
90
+ puts "Scheduling new instance of #{worker_klass}"
91
+ Process.kill(:USR1, running_pid(worker_klass))
92
+ end
88
93
  end
94
+ end
95
+
96
+ def dispose(*workers)
97
+ perform_action(:dispose, workers) do |worker_klass|
98
+ unless running?(worker_klass)
99
+ puts "#{worker_klass}'s manager not running yet"
100
+ exit(1)
101
+ end
89
102
 
90
- run_callbacks(:dispose) do
91
103
  Process.kill(:USR2, running_pid(worker_klass))
92
104
  end
93
105
  end
@@ -107,8 +119,26 @@ module Workforce
107
119
  Config.instance.after(event).each { |callback| callback.call }
108
120
  end
109
121
 
122
+ def available_workers
123
+ Dir["#{Config.get(:workers_dir)}/*"].map do |file|
124
+ worker_name = Inflector.camelcase(File.basename(file, ".rb"))
125
+ get_klass(worker_name)
126
+ end
127
+ end
128
+
129
+ def perform_action(action, workers, &block)
130
+ run_callbacks(action) do
131
+ if workers.empty?
132
+ workers = available_workers
133
+ else
134
+ workers = workers.map { |worker_name| get_klass(worker_name) }
135
+ end
136
+ workers.each(&block)
137
+ end
138
+ end
139
+
110
140
  def pid_file(worker_klass)
111
- "#{Workforce::Config.get(:pid_dir)}/#{Workforce::Inflector.underscore(worker_klass)}.pid"
141
+ "#{Workforce::Config.get(:pid_dir)}/#{Workforce::Inflector.underscore(worker_klass.to_s)}.pid"
112
142
  end
113
143
 
114
144
  def running?(worker_klass)
@@ -46,7 +46,6 @@ module Workforce
46
46
  log_errors do
47
47
  logger.info "Starting manager for #{@worker}"
48
48
 
49
- @running = true
50
49
  $0 = "Workforce: #{@worker.name} master"
51
50
 
52
51
  trap_signal(:INT, :shutdown)
@@ -59,6 +58,8 @@ module Workforce
59
58
  logger.info "Removing process (#{pid}) from worker pool"
60
59
  @pids.delete(pid)
61
60
  end
61
+
62
+ @running = true
62
63
 
63
64
  # Block process until something is written to @pipe_out
64
65
  IO.select([@pipe_in], nil, nil, nil)
@@ -3,3 +3,5 @@ base_path = File.dirname(__FILE__)
3
3
  workers_dir "#{base_path}/workers"
4
4
  pid_dir "#{base_path}/pid"
5
5
  log_dir "#{base_path}/log"
6
+
7
+ schedule :SleepDaemon, 5
@@ -0,0 +1,5 @@
1
+ class SleepDaemon2
2
+ def run
3
+ loop { sleep 1 }
4
+ end
5
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{workforce}
8
- s.version = "0.2.4"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rodrigo Kochenburger"]
12
- s.date = %q{2010-05-31}
12
+ s.date = %q{2010-07-05}
13
13
  s.default_executable = %q{workforce}
14
14
  s.description = %q{Workforce is an attempt to create a framework to develop background processes and controlling the execution of these processes in a distributed environment}
15
15
  s.email = %q{divoxx@gmail.com}
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "LICENSE",
25
25
  "README.md",
26
26
  "Rakefile",
27
+ "TODO.md",
27
28
  "VERSION",
28
29
  "bin/workforce",
29
30
  "lib/workforce.rb",
@@ -33,6 +34,7 @@ Gem::Specification.new do |s|
33
34
  "lib/workforce/manager.rb",
34
35
  "sample/config_sample.rb",
35
36
  "sample/workers/sleep_daemon.rb",
37
+ "sample/workers/sleep_daemon2.rb",
36
38
  "spec/spec.opts",
37
39
  "spec/spec_helper.rb",
38
40
  "workforce.gemspec"
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 4
9
- version: 0.2.4
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Rodrigo Kochenburger
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-31 00:00:00 -03:00
17
+ date: 2010-07-05 00:00:00 -03:00
18
18
  default_executable: workforce
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -60,6 +60,7 @@ files:
60
60
  - LICENSE
61
61
  - README.md
62
62
  - Rakefile
63
+ - TODO.md
63
64
  - VERSION
64
65
  - bin/workforce
65
66
  - lib/workforce.rb
@@ -69,6 +70,7 @@ files:
69
70
  - lib/workforce/manager.rb
70
71
  - sample/config_sample.rb
71
72
  - sample/workers/sleep_daemon.rb
73
+ - sample/workers/sleep_daemon2.rb
72
74
  - spec/spec.opts
73
75
  - spec/spec_helper.rb
74
76
  - workforce.gemspec