Permalink
Browse files

Improved shutdown

  • Loading branch information...
1 parent 2a28874 commit 0321aad6b6fceb9f9c20a1647f329a9f2d72cb2a @burke committed Aug 27, 2012
Showing with 184 additions and 152 deletions.
  1. +9 −9 a.rb
  2. +4 −6 docs/master_slave_handshake.md
  3. +0 −6 docs/message_format.md
  4. +9 −0 fake_zeus.rb
  5. +83 −79 zeus_rails.rb
  6. +7 −2 zeusmaster/filemonitor.go
  7. +0 −1 zeusmaster/processtree.go
  8. +48 −36 zeusmaster/slavemonitor.go
  9. +24 −13 zeusmaster/zeusmaster.go
View
18 a.rb
@@ -1,14 +1,15 @@
require 'socket'
+require './fake_zeus'
def report_error_to_master(local, e)
local.write "R:FAIL"
end
-def run_action(socket, action)
- action.sub!(/^A:/,'')
- eval action
+def run_action(socket, identifier)
+ FakeZeus.send(identifier)
socket.write "R:OK"
rescue Exception => e
+ File.open("wtf.log", "a") {|f| f.puts e.inspect , e.backtrace}
report_error_to_master(socket, e)
end
@@ -24,8 +25,9 @@ def handle_dead_children
rescue Errno::ECHLD
end
-def go(identifier=nil)
- $0 = "zeus slave: #{identifier || "(root)"}"
+def go(identifier=:boot)
+ identifier = identifier.to_sym
+ $0 = "zeus slave: #{identifier}"
# okay, so I ahve this FD that I can use to send data to the master.
fd = ENV['ZEUS_MASTER_FD'].to_i
master = UNIXSocket.for_fd(fd)
@@ -37,10 +39,8 @@ def go(identifier=nil)
# Now I need to tell the master about my PID and ID
local.write "P:#{Process.pid}:#{identifier}"
- # So now we have to wait for the master to identify us and send our action.
- # We'll run the action right away and then report status to the master.
- action = local.recv(65536) # TODO: just chunk this?
- run_action(local, action)
+ # Now we run the action and report its success/fail status to the master.
+ run_action(local, identifier)
# the master wants to know about the files that running the action caused us to load.
Thread.new { notify_newly_loaded_files }
@@ -18,14 +18,12 @@ passes along to the newly-forked process.
The Slave sends a "Pid & Identifier" message containing the pid and the identifier (blank if initial process)
-#### 3. Action
-
-The Master now sends, along `remote`, a string containing the code representing the action for this Slave.
-
-The Slave evaluates this code.
-
#### 4. Action Result
+The Slave now executes the code it's intended to run by looking up the action
+in a collection of predefined actions indexed by identifier. In ruby this is implemented
+as a module that responds to a method named according to each identifier.
+
If there were no runtime errors in evaluating the action, the Slave writes "OK" to `local`.
If there were runtime errors, the slave returns a string representing the errors in an arbitrary and
View
@@ -15,12 +15,6 @@ It is formed by joining the process's pid and identifier with a colon.
Example: `P:1235:default_bundle`
-#### Action message (`A`, `SlaveMonitor`)
-
-This is sent from the Master to the Slave, and contains the action code to execute.
-
-Example: `A:require 'rails/all'\nBundler.require(:default)\n`
-
#### Action response message (`R`, `SlaveMonitor`)
This is sent from the Slave to the Master once the action has executed.
View
@@ -0,0 +1,9 @@
+module FakeZeus
+ class << self
+ def method_missing(s, *a)
+ sleep 1.5
+ File.open("omg.log", "a") { |f| f.puts "FakeZeus.#{s}" }
+ end
+ end
+end
+
View
@@ -1,107 +1,111 @@
module ZeusRails
+ ROOT_PATH = File.expand_path(Dir.pwd)
ENV_PATH = File.expand_path('config/environment', ROOT_PATH)
BOOT_PATH = File.expand_path('config/boot', ROOT_PATH)
APP_PATH = File.expand_path('config/application', ROOT_PATH)
- def boot
- require BOOT_PATH
- require 'rails/all'
- end
-
- def default_bundle
- Bundler.require(:default)
- end
+ class << self
- def development_environment
- Bundler.require(:development)
- Rails.env = ENV['RAILS_ENV'] = "development"
- require APP_PATH
- Rails.application.require_environment!
- end
+ def boot
+ require BOOT_PATH
+ require 'rails/all'
+ end
- def prerake
- require 'rake'
- load 'Rakefile'
- end
+ def default_bundle
+ Bundler.require(:default)
+ end
- def rake
- Rake.application.run
- end
+ def development_environment
+ Bundler.require(:development)
+ Rails.env = ENV['RAILS_ENV'] = "development"
+ require APP_PATH
+ Rails.application.require_environment!
+ end
- def generate
- begin
- require 'rails/generators'
- Rails.application.load_generators
- rescue LoadError # Rails 3.0 doesn't require this block to be run, but 3.2+ does
+ def prerake
+ require 'rake'
+ load 'Rakefile'
end
- require 'rails/commands/generate'
- end
- def runner
- require 'rails/commands/runner'
- end
+ def rake
+ Rake.application.run
+ end
- def console
- require 'rails/commands/console'
- Rails::Console.start(Rails.application)
- end
+ def generate
+ begin
+ require 'rails/generators'
+ Rails.application.load_generators
+ rescue LoadError # Rails 3.0 doesn't require this block to be run, but 3.2+ does
+ end
+ require 'rails/commands/generate'
+ end
- def server
- require 'rails/commands/server'
- server = Rails::Server.new
- Dir.chdir(Rails.application.root)
- server.start
- end
+ def runner
+ require 'rails/commands/runner'
+ end
- def test_environment
- Bundler.require(:test)
+ def console
+ require 'rails/commands/console'
+ Rails::Console.start(Rails.application)
+ end
- Rails.env = ENV['RAILS_ENV'] = 'test'
- require APP_PATH
+ def server
+ require 'rails/commands/server'
+ server = Rails::Server.new
+ Dir.chdir(Rails.application.root)
+ server.start
+ end
- $rails_rake_task = 'yup' # lie to skip eager loading
- Rails.application.require_environment!
- $rails_rake_task = nil
- $LOAD_PATH.unshift(ROOT_PATH) unless $LOAD_PATH.include?(ROOT_PATH)
+ def test_environment
+ Bundler.require(:test)
- if Dir.exist?(ROOT_PATH + "/test")
- test = File.join(ROOT_PATH, 'test')
- $LOAD_PATH.unshift(test) unless $LOAD_PATH.include?(test)
- end
+ Rails.env = ENV['RAILS_ENV'] = 'test'
+ require APP_PATH
- if Dir.exist?(ROOT_PATH + "/spec")
- spec = File.join(ROOT_PATH, 'spec')
- $LOAD_PATH.unshift(spec) unless $LOAD_PATH.include?(spec)
- end
- end
+ $rails_rake_task = 'yup' # lie to skip eager loading
+ Rails.application.require_environment!
+ $rails_rake_task = nil
+ $LOAD_PATH.unshift(ROOT_PATH) unless $LOAD_PATH.include?(ROOT_PATH)
- def test_helper
- require 'test_helper'
- end
+ if Dir.exist?(ROOT_PATH + "/test")
+ test = File.join(ROOT_PATH, 'test')
+ $LOAD_PATH.unshift(test) unless $LOAD_PATH.include?(test)
+ end
- def testrb
- argv = ARGV
+ if Dir.exist?(ROOT_PATH + "/spec")
+ spec = File.join(ROOT_PATH, 'spec')
+ $LOAD_PATH.unshift(spec) unless $LOAD_PATH.include?(spec)
+ end
+ end
- # try to find pattern by line using testrbl
- if defined?(Testrbl) && argv.size == 1 and argv.first =~ /^\S+:\d+$/
- file, line = argv.first.split(':')
- argv = [file, '-n', "/#{Testrbl.send(:pattern_from_file, File.readlines(file), line)}/"]
- puts "using -n '#{argv[2]}'" # let users copy/paste or adjust the pattern
+ def test_helper
+ require 'test_helper'
end
- runner = Test::Unit::AutoRunner.new(true)
- if runner.process_args(argv)
- exit runner.run
- else
- abort runner.options.banner + " tests..."
+ def testrb
+ argv = ARGV
+
+ # try to find pattern by line using testrbl
+ if defined?(Testrbl) && argv.size == 1 and argv.first =~ /^\S+:\d+$/
+ file, line = argv.first.split(':')
+ argv = [file, '-n', "/#{Testrbl.send(:pattern_from_file, File.readlines(file), line)}/"]
+ puts "using -n '#{argv[2]}'" # let users copy/paste or adjust the pattern
+ end
+
+ runner = Test::Unit::AutoRunner.new(true)
+ if runner.process_args(argv)
+ exit runner.run
+ else
+ abort runner.options.banner + " tests..."
+ end
end
- end
- def spec_helper
- require 'spec_helper'
- end
+ def spec_helper
+ require 'spec_helper'
+ end
- def rspec
- exit RSpec::Core::Runner.run(ARGV)
+ def rspec
+ exit RSpec::Core::Runner.run(ARGV)
+ end
end
end
@@ -3,6 +3,11 @@ package zeusmaster
func StartFileMonitor(tree *ProcessTree, quit chan bool) {
println("RUNNING FILEMONITOR")
- <- quit
- quit <- true
+ for {
+ select {
+ case <- quit:
+ quit <- true
+ return
+ }
+ }
}
@@ -16,7 +16,6 @@ type ProcessTreeNode struct {
mu sync.RWMutex
Parent *SlaveNode
Name string
- Action string
}
type SlaveNode struct {
Oops, something went wrong.

0 comments on commit 0321aad

Please sign in to comment.