workforce 0.2.4 → 0.3.0

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