Module: Einhorn::Worker
- Defined in:
- lib/einhorn/worker.rb
Defined Under Namespace
Classes: WorkerError
Class Method Summary collapse
- .ack(*args) ⇒ Object
-
.ack!(discovery = :env, arg = nil) ⇒ Object
Call this once your app is up and running in a good state.
-
.einhorn_child_index ⇒ Object
Returns the index of this Einhorn child process.
- .einhorn_fd(n) ⇒ Object
- .einhorn_fd_count ⇒ Object
- .ensure_worker! ⇒ Object
-
.graceful_shutdown(&blk) ⇒ Object
Call this to handle graceful shutdown requests to your app.
- .is_worker? ⇒ Boolean
- .socket(number = nil) ⇒ Object
- .socket!(number = nil) ⇒ Object
Class Method Details
.ack(*args) ⇒ Object
29 30 31 32 33 34 |
# File 'lib/einhorn/worker.rb', line 29 def self.ack(*args) begin ack!(*args) rescue WorkerError end end |
.ack!(discovery = :env, arg = nil) ⇒ Object
Call this once your app is up and running in a good state. Arguments:
@discovery: How to discover the master process’s command socket.
:env: Discover the path from ENV['EINHORN_SOCK_PATH']
:fd: Just use the file descriptor in ENV['EINHORN_SOCK_FD'].
Must run the master with the -g flag. This is mostly
useful if you don't have a nice library like Einhorn::Worker.
Then @arg being true causes the FD to be left open after ACK;
otherwise it is closed.
:direct: Provide the path to the command socket in @arg.
TODO: add a :fileno option? Easy to implement; not sure if it’d be useful for anything. Maybe if it’s always fd 3, because then the user wouldn’t have to provide an arg.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/einhorn/worker.rb', line 68 def self.ack!(discovery=:env, arg=nil) ensure_worker! close_after_use = true case discovery when :env socket = ENV['EINHORN_SOCK_PATH'] client = Einhorn::Client.for_path(socket) when :fd raise "No EINHORN_SOCK_FD provided in environment. Did you run einhorn with the -g flag?" unless fd_str = ENV['EINHORN_SOCK_FD'] fd = Integer(fd_str) client = Einhorn::Client.for_fd(fd) close_after_use = false if arg when :direct socket = arg client = Einhorn::Client.for_path(socket) else raise "Unrecognized socket discovery mechanism: #{discovery.inspect}. Must be one of :filesystem, :argv, or :direct" end client.send_command({ 'command' => 'worker:ack', 'pid' => $$ }) client.close if close_after_use true end |
.einhorn_child_index ⇒ Object
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.
44 45 46 47 48 49 50 51 |
# File 'lib/einhorn/worker.rb', line 44 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 |
.einhorn_fd(n) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/einhorn/worker.rb', line 121 def self.einhorn_fd(n) unless raw_fd = ENV["EINHORN_FD_#{n}"] return nil end Integer(raw_fd) end |
.einhorn_fd_count ⇒ Object
128 129 130 131 132 133 |
# File 'lib/einhorn/worker.rb', line 128 def self.einhorn_fd_count unless raw_count = ENV['EINHORN_FD_COUNT'] return 0 end Integer(raw_count) end |
.ensure_worker! ⇒ Object
18 19 20 21 22 23 24 25 26 27 |
# File 'lib/einhorn/worker.rb', line 18 def self.ensure_worker! # Make sure that EINHORN_MASTER_PID is my parent if ppid_s = ENV['EINHORN_MASTER_PID'] ppid = ppid_s.to_i raise WorkerError.new("EINHORN_MASTER_PID environment variable is #{ppid_s.inspect}, but my parent's pid is #{Process.ppid.inspect}. This probably means that I am a subprocess of an Einhorn worker, but am not one myself.") unless Process.ppid == ppid true else raise WorkerError.new("No EINHORN_MASTER_PID environment variable set. Are you running your process under Einhorn?") unless Process.ppid == ppid end end |
.graceful_shutdown(&blk) ⇒ Object
Call this to handle graceful shutdown requests to your app.
136 137 138 |
# File 'lib/einhorn/worker.rb', line 136 def self.graceful_shutdown(&blk) Signal.trap('USR2', &blk) end |
.is_worker? ⇒ Boolean
8 9 10 11 12 13 14 15 16 |
# File 'lib/einhorn/worker.rb', line 8 def self.is_worker? begin ensure_worker! rescue WorkerError false else true end end |
.socket(number = nil) ⇒ Object
98 99 100 101 |
# File 'lib/einhorn/worker.rb', line 98 def self.socket(number=nil) number ||= 0 einhorn_fd(number) end |
.socket!(number = nil) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/einhorn/worker.rb', line 103 def self.socket!(number=nil) number ||= 0 unless count = einhorn_fd_count raise "No EINHORN_FD_COUNT provided in environment. Are you running under Einhorn?" end unless number < count raise "Only #{count} FDs available, but FD #{number} was requested" end unless fd = einhorn_fd(number) raise "No EINHORN_FD_#{number} provided in environment. That's pretty weird" end fd end |