fate 0.2.20 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/fate CHANGED
@@ -12,14 +12,14 @@ $LOAD_PATH.unshift("#{FATE_ROOT}/lib")
12
12
  require "fate"
13
13
 
14
14
  options = {
15
- :configuration => "fate.json",
15
+ :specification => "fate.json",
16
16
  :default_log => STDOUT
17
17
  }
18
18
 
19
19
  # TODO: config file flag
20
20
  OptionParser.new do |parser|
21
21
  parser.on("-c", "--configuration=FILE", "The origin of the events") do |file|
22
- options[:configuration] = file
22
+ options[:specification] = file
23
23
  end
24
24
  parser.on("-l", "--log=FILE", "Processes log to FILE") do |file|
25
25
  options[:default_log] = File.new(file, "a")
@@ -27,14 +27,13 @@ OptionParser.new do |parser|
27
27
  end.parse!
28
28
 
29
29
 
30
- string = File.read(options[:configuration])
31
- configuration = JSON.parse(string, :symbolize_names => true)
32
- fate = Fate.new(configuration, options)
33
-
30
+ string = File.read(options[:specification])
31
+ specification = JSON.parse(string, :symbolize_names => true)
34
32
 
33
+ fate = Fate.new(specification, options)
35
34
 
36
35
  require "fate/repl"
37
- fate.start(ARGV)
38
- fate.repl
36
+ fate.control.start(*ARGV)
37
+ fate.control.repl
39
38
 
40
39
 
@@ -13,104 +13,67 @@ class Fate
13
13
  self.new(specification).start(&block)
14
14
  end
15
15
 
16
- attr_reader :service, :manager, :completions, :logger
16
+ attr_reader :service, :manager, :control
17
+ def initialize(specification, options)
18
+ @service = Fate::Service.new(specification, options)
19
+ @manager = Fate::ProcessManager.new(service, options)
20
+ @control = Fate::Control.new(@manager, options)
21
+ end
17
22
 
18
- def initialize(spec, options={})
19
- @service = Service.new(spec, options)
20
- @completions = @service.completions
23
+ class Control
21
24
 
22
- @spec = spec
23
- @logger = @service.logger["Fate Control"]
25
+ attr_reader :service, :manager, :completions, :logger
24
26
 
25
- @manager = ProcessManager.new(@service, options)
26
- end
27
+ def initialize(manager, options={})
28
+ @manager = manager
29
+ @service = @manager.service
30
+ @completions = @service.completions
27
31
 
28
- def log(*args, &block)
29
- @logger.log(*args, &block)
30
- end
32
+ @spec = @service.specification
33
+ @logger = @service.logger["Fate Control"]
34
+ end
31
35
 
32
- def run(&block)
33
- if start
34
- if block
35
- yield(self)
36
- stop
37
- end
38
- else
39
- logger.error "Failed to start"
36
+ def log(*args, &block)
37
+ @logger.log(*args, &block)
40
38
  end
41
- end
42
39
 
43
- def start(command_specs=[])
44
- if command_specs.size > 0
45
- command_specs.each do |command_spec|
46
- self.start_command(command_spec)
47
- end
48
- else
49
- if manager.start_group(@service.commands)
50
- logger.green "All commands are running."
51
- true
40
+ def start(*command_strings)
41
+ if manager.start(command_strings)
42
+ logger.green "All processes are running."
52
43
  else
53
- false
44
+ logger.error "Failed to start."
54
45
  end
55
46
  end
56
- end
57
-
58
- def stop
59
- manager.stop_all
60
- end
61
47
 
62
- def restart
63
- stop
64
- start
65
- end
66
-
67
- def start_command(command_spec)
68
- names = @service.resolve_commands(command_spec)
69
- if names.empty?
70
- puts "No commands found for: #{command_spec}"
71
- else
72
- commands = {}
73
- names.each do |name|
74
- command = @service.commands[name]
75
- commands[name] = command
76
- end
77
- if manager.start_group(commands)
78
- logger.green "All commands in '#{command_spec}' running."
79
- else
80
- logger.error "Failed to start '#{command_spec}'."
81
- end
48
+ def stop(*command_strings)
49
+ manager.stop(command_strings)
82
50
  end
83
- end
84
51
 
85
- def stop_command(command_spec)
86
- names = @service.resolve_commands(command_spec)
87
- if names.empty?
88
- puts "No commands found for: #{command_spec}"
89
- else
90
- names.each do |name|
91
- manager.stop_command(name)
92
- end
52
+ def restart(*command_strings)
53
+ stop(command_strings)
54
+ start(command_strings)
93
55
  end
94
- end
95
56
 
96
- def restart_command(name)
97
- stop_command(name)
98
- start_command(name)
99
- end
57
+ # Run only the processes specified by the arguments. Any existing
58
+ # processes outside this set will be stopped.
59
+ def run(*command_strings)
60
+ manager.run(command_strings)
61
+ end
100
62
 
101
- def running
102
- manager.running
103
- end
63
+ def running
64
+ manager.running
65
+ end
104
66
 
105
- # ad hoc shell out, with rescuing because of some apparent bugs
106
- # in MRI 1.8.7's ability to cope with unusual exit codes.
107
- def system(command)
108
- begin
109
- Kernel.system command
110
- rescue => error
111
- puts "Exception raised when executing '#{command}': #{error.inspect}"
67
+ # ad hoc shell out, with rescuing because of some apparent bugs
68
+ # in MRI 1.8.7's ability to cope with unusual exit codes.
69
+ def system(command)
70
+ begin
71
+ Kernel.system command
72
+ rescue => error
73
+ puts "Exception raised when executing '#{command}': #{error.inspect}"
74
+ end
112
75
  end
113
- end
114
76
 
77
+ end
115
78
  end
116
79
 
@@ -6,7 +6,7 @@ class Fate
6
6
  # processes, tracking them by name, and handling unexpected exits and signals.
7
7
  class ProcessManager
8
8
 
9
- attr_reader :logger, :output_handlers
9
+ attr_reader :logger, :output_handlers, :service
10
10
  def initialize(service, options={})
11
11
  @directory = options[:directory]
12
12
  @mutex = Mutex.new
@@ -19,32 +19,66 @@ class Fate
19
19
  @names_by_pid = {}
20
20
  @pids_by_name = {}
21
21
  at_exit do
22
- stop_all
22
+ stop_group(running)
23
23
  end
24
24
  end
25
25
 
26
- def stop_all
27
- @mutex.synchronize do
28
- ordered = @service.stop_order(running)
29
- ordered.each do |name|
30
- term(name)
31
- end
26
+ def run(command_strings=[])
27
+ if command_strings.empty?
28
+ run(@service.commands.keys)
29
+ else
30
+ commands = @service.resolve(command_strings)
31
+ # don't need to start processes that are already running
32
+ noop = commands & running
33
+ to_start = commands - noop
34
+ to_stop = running - commands
35
+
36
+ stop_group(to_stop)
37
+ start_group(to_start)
38
+ end
39
+ end
40
+
41
+ def start(command_strings=[])
42
+ if command_strings.empty?
43
+ start_group(@service.commands.keys)
44
+ else
45
+ commands = @service.resolve(command_strings)
46
+ start_group(commands)
47
+ end
48
+ end
49
+
50
+ def stop(command_strings=[])
51
+ if command_strings.empty?
52
+ stop_group(running)
53
+ else
54
+ names = @service.resolve(command_strings)
55
+ stop_group(names)
32
56
  end
33
57
  end
34
58
 
35
- def start_group(hash)
36
- hash.each do |name, command|
59
+ def start_group(names)
60
+ ordered = @service.start_order(names)
61
+ ordered.each do |name|
62
+ command = service.commands[name]
37
63
  @commands_by_name[name] = command
38
64
  start_command(name, command) unless @down_in_flames
39
65
  end
40
-
41
- until hash.keys.all? { |key| @threads[key] }
66
+ until names.all? { |name| @threads[name] }
42
67
  return false if @down_in_flames
43
68
  sleep 0.1
44
69
  end
45
70
  return true
46
71
  end
47
72
 
73
+ def stop_group(names)
74
+ @mutex.synchronize do
75
+ ordered = @service.stop_order(names)
76
+ ordered.each do |name|
77
+ term(name)
78
+ end
79
+ end
80
+ end
81
+
48
82
  def start_command(name, command)
49
83
  if pid = @pids_by_name[name]
50
84
  logger.warn "'#{name}' is already running with pid #{pid}"
@@ -53,10 +87,6 @@ class Fate
53
87
  end
54
88
  end
55
89
 
56
- def stop_command(name)
57
- term(name)
58
- end
59
-
60
90
  def term(name)
61
91
  if pid = @pids_by_name[name]
62
92
  @names_by_pid.delete(pid)
@@ -164,22 +194,11 @@ class Fate
164
194
  end
165
195
  logger.info "Shutting down all processes."
166
196
 
167
- stop_all
197
+ stop_group(running)
168
198
  exit(1)
169
199
  end
170
200
 
171
201
 
172
- # ad hoc shell out, with rescuing because of some apparent bugs
173
- # in MRI 1.8.7's ability to cope with unusual exit codes.
174
- def system(command)
175
- #begin
176
- Kernel.system command
177
- #rescue => error
178
- #puts "Exception raised when executing '#{command}': #{error.inspect}"
179
- #end
180
- end
181
-
182
-
183
202
 
184
203
  end
185
204
  end
@@ -1,53 +1,68 @@
1
1
  require "harp"
2
2
  class Fate
3
+ class Control
3
4
 
4
- include Harp
5
+ include Harp
5
6
 
6
- setup_harp do |harp|
7
+ setup_harp do |harp|
7
8
 
8
- command("help") do
9
- commands = harp.command_names.select {|c| c.size > 1 } + ["!"]
10
- puts "* Available commands: " << commands.sort.join(" ")
11
- end
9
+ command("help") do
10
+ commands = harp.command_names.select {|c| c.size > 1 } + ["!"]
11
+ puts "* Available commands: " << commands.sort.join(" ")
12
+ end
12
13
 
13
- command("quit", :alias => "q") { exit }
14
- command("exit") { exit }
14
+ command("quit", :alias => "q") { exit }
15
+ command("exit") { exit }
15
16
 
16
- command("stop") do
17
- self.stop
18
- end
17
+ command("stop") do
18
+ self.stop
19
+ end
19
20
 
20
- command("stop", :process_name) do |args|
21
- command = args.first
22
- self.stop_command(args.first)
23
- end
21
+ command("stop", :process_name) do |args|
22
+ command = args.first
23
+ self.stop(args.first)
24
+ end
24
25
 
25
- command("start", :process_name) do |args|
26
- command = args.first
27
- self.start_command(args.first)
28
- end
26
+ command("run") do
27
+ self.run
28
+ end
29
29
 
30
- command("restart") do
31
- self.restart
32
- end
30
+ command("run", :process_name) do |args|
31
+ command = args.first
32
+ self.run(args.first)
33
+ end
33
34
 
34
- command("restart", :process_name) do |args|
35
- command = args.first
36
- self.restart_command(args.first)
37
- end
35
+ command("start", :process_name) do |args|
36
+ command = args.first
37
+ self.start(args.first)
38
+ end
38
39
 
39
- command("processes") do
40
- puts self.service.names
41
- end
40
+ command("restart") do
41
+ self.restart
42
+ end
42
43
 
43
- command("running") do
44
- puts self.running
45
- end
44
+ command("restart", :process_name) do |args|
45
+ command = args.first
46
+ self.restart(args.first)
47
+ end
48
+
49
+ command("processes") do
50
+ puts self.service.names
51
+ end
52
+
53
+ #command("groups") do
54
+ #end
55
+
56
+ command("running") do
57
+ puts self.running
58
+ end
59
+
60
+ command("configuration") do
61
+ puts JSON.pretty_generate(self.service.specification)
62
+ end
46
63
 
47
- command("configuration") do
48
- puts JSON.pretty_generate(self.service.specification)
49
64
  end
50
65
 
51
66
  end
52
-
53
67
  end
68
+
@@ -95,6 +95,19 @@ class Fate
95
95
  out
96
96
  end
97
97
 
98
+ def resolve(specs)
99
+ command_names = []
100
+ specs.each do |spec|
101
+ names = resolve_commands(spec)
102
+ if names.empty?
103
+ logger.warn "Fate", "No commands found for: #{spec}"
104
+ else
105
+ command_names.concat(names)
106
+ end
107
+ end
108
+ names = command_names.uniq
109
+ end
110
+
98
111
  def resolve_commands(name)
99
112
  targets = []
100
113
  if @commands.has_key?(name)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.20
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-06 00:00:00.000000000 Z
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json