Skip to content

Commit

Permalink
Pass each child a unique index number.
Browse files Browse the repository at this point in the history
This allows for running N differentiated children within an einhorn
supervisor.
  • Loading branch information
nelhage-stripe authored and nelhage committed Apr 5, 2014
1 parent a9cba13 commit 850767d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
21 changes: 16 additions & 5 deletions lib/einhorn/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,16 @@ def self.reload
end
end

def self.next_index
all_indexes = Set.new(Einhorn::State.children.map { |k, st| st[:index] })
0.upto(all_indexes.length) do |i|
return i unless all_indexes.include?(i)
end
end

def self.spinup(cmd=nil)
cmd ||= Einhorn::State.cmd
index = next_index
if Einhorn::TransientState.preloaded
pid = fork do
Einhorn::TransientState.whatami = :worker
Expand All @@ -234,7 +242,7 @@ def self.spinup(cmd=nil)

reseed_random

prepare_child_environment
prepare_child_environment(index)
einhorn_main
end
else
Expand All @@ -251,17 +259,18 @@ def self.spinup(cmd=nil)
# Note that Ruby 1.9's close_others option is useful here.
Einhorn::Event.close_all_for_worker

prepare_child_environment
prepare_child_environment(index)
Einhorn::Compat.exec(cmd[0], cmd[1..-1], :close_others => false)
end
end

Einhorn.log_info("===> Launched #{pid}", :upgrade)
Einhorn.log_info("===> Launched #{pid} (index: #{index})", :upgrade)
Einhorn::State.children[pid] = {
:type => :worker,
:version => Einhorn::State.version,
:acked => false,
:signaled => Set.new
:signaled => Set.new,
:index => index
}
Einhorn::State.last_spinup = Time.now

Expand All @@ -276,7 +285,7 @@ def self.spinup(cmd=nil)
end
end

def self.prepare_child_environment
def self.prepare_child_environment(index)
# This is run from the child
ENV['EINHORN_MASTER_PID'] = Process.ppid.to_s
ENV['EINHORN_SOCK_PATH'] = Einhorn::Command::Interface.socket_path
Expand All @@ -289,6 +298,8 @@ def self.prepare_child_environment
ENV['EINHORN_FD_COUNT'] = Einhorn::State.bind_fds.length.to_s
Einhorn::State.bind_fds.each_with_index {|fd, i| ENV["EINHORN_FD_#{i}"] = fd.to_s}

ENV['EINHORN_CHILD_INDEX'] = index.to_s

# EINHORN_FDS is deprecated. It was originally an attempt to
# match Upstart's nominal internal support for space-separated
# FD lists, but nobody uses that in practice, and it makes
Expand Down
17 changes: 17 additions & 0 deletions lib/einhorn/worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ def self.ack(*args)
end
end

# Returns the index of this Einhorn child process.
#
# If an Einhorn master has N children, this will be an integer in
# the range [0,N), and no two workers running concurrently will
# ever have the same index.
#
# Returns nil if not running in Einhorn, or running on a version
# of Einhorn that does not support indexing children.
def self.einhorn_child_index
index = ENV['EINHORN_CHILD_INDEX']
if index.nil? || index !~ /\A \d+ \z/x
index
else
index.to_i
end
end

# Call this once your app is up and running in a good state.
# Arguments:
#
Expand Down

0 comments on commit 850767d

Please sign in to comment.