Module: Einhorn::Worker

Defined in:
lib/einhorn/worker.rb

Defined Under Namespace

Classes: WorkerError

Class Method Summary collapse

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.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/einhorn/worker.rb', line 51

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.command({
      'command' => 'worker:ack',
      'pid' => $$
    })

  client.close if close_after_use
  true
end

.einhorn_fd(n) ⇒ Object



104
105
106
107
108
109
# File 'lib/einhorn/worker.rb', line 104

def self.einhorn_fd(n)
  unless raw_fd = ENV["EINHORN_FD_#{n}"]
    return nil
  end
  Integer(raw_fd)
end

.einhorn_fd_countObject



111
112
113
114
115
116
# File 'lib/einhorn/worker.rb', line 111

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.



119
120
121
# File 'lib/einhorn/worker.rb', line 119

def self.graceful_shutdown(&blk)
  Signal.trap('USR2', &blk)
end

.is_worker?Boolean

Returns:

  • (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



81
82
83
84
# File 'lib/einhorn/worker.rb', line 81

def self.socket(number=nil)
  number ||= 0
  einhorn_fd(number)
end

.socket!(number = nil) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/einhorn/worker.rb', line 86

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