fate 0.2.20 → 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/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