einhorn 0.7.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/Changes.md +10 -0
  3. data/README.md +36 -30
  4. data/bin/einhorn +17 -2
  5. data/einhorn.gemspec +23 -21
  6. data/example/pool_worker.rb +1 -1
  7. data/example/thin_example +8 -8
  8. data/example/time_server +5 -5
  9. data/lib/einhorn/client.rb +8 -9
  10. data/lib/einhorn/command/interface.rb +100 -95
  11. data/lib/einhorn/command.rb +167 -88
  12. data/lib/einhorn/compat.rb +7 -7
  13. data/lib/einhorn/event/abstract_text_descriptor.rb +31 -35
  14. data/lib/einhorn/event/ack_timer.rb +2 -2
  15. data/lib/einhorn/event/command_server.rb +7 -9
  16. data/lib/einhorn/event/connection.rb +1 -3
  17. data/lib/einhorn/event/loop_breaker.rb +2 -1
  18. data/lib/einhorn/event/persistent.rb +2 -2
  19. data/lib/einhorn/event/timer.rb +4 -4
  20. data/lib/einhorn/event.rb +29 -20
  21. data/lib/einhorn/prctl.rb +26 -0
  22. data/lib/einhorn/prctl_linux.rb +48 -0
  23. data/lib/einhorn/safe_yaml.rb +17 -0
  24. data/lib/einhorn/version.rb +1 -1
  25. data/lib/einhorn/worker.rb +67 -49
  26. data/lib/einhorn/worker_pool.rb +9 -9
  27. data/lib/einhorn.rb +155 -126
  28. metadata +42 -137
  29. data/.gitignore +0 -17
  30. data/.travis.yml +0 -10
  31. data/CONTRIBUTORS +0 -6
  32. data/Gemfile +0 -11
  33. data/History.txt +0 -4
  34. data/README.md.in +0 -76
  35. data/Rakefile +0 -27
  36. data/test/_lib.rb +0 -12
  37. data/test/integration/_lib/fixtures/env_printer/env_printer.rb +0 -26
  38. data/test/integration/_lib/fixtures/exit_during_upgrade/exiting_server.rb +0 -22
  39. data/test/integration/_lib/fixtures/exit_during_upgrade/upgrade_reexec.rb +0 -6
  40. data/test/integration/_lib/fixtures/upgrade_project/upgrading_server.rb +0 -22
  41. data/test/integration/_lib/helpers/einhorn_helpers.rb +0 -143
  42. data/test/integration/_lib/helpers.rb +0 -4
  43. data/test/integration/_lib.rb +0 -6
  44. data/test/integration/startup.rb +0 -31
  45. data/test/integration/upgrading.rb +0 -157
  46. data/test/unit/einhorn/client.rb +0 -88
  47. data/test/unit/einhorn/command/interface.rb +0 -49
  48. data/test/unit/einhorn/command.rb +0 -21
  49. data/test/unit/einhorn/event.rb +0 -89
  50. data/test/unit/einhorn/worker_pool.rb +0 -39
  51. data/test/unit/einhorn.rb +0 -58
  52. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -2,7 +2,7 @@ module Einhorn::Event
2
2
  class ACKTimer < Timer
3
3
  include Persistent
4
4
 
5
- def initialize(time, pid, start=nil)
5
+ def initialize(time, pid, start = nil)
6
6
  super(time, start) do
7
7
  Einhorn::Command.register_timer_ack(time, pid)
8
8
  end
@@ -10,7 +10,7 @@ module Einhorn::Event
10
10
  end
11
11
 
12
12
  def to_state
13
- {:class => self.class.to_s, :time => @time, :start => @start, :pid => @pid}
13
+ {class: self.class.to_s, time: @time, start: @start, pid: @pid}
14
14
  end
15
15
 
16
16
  def self.from_state(state)
@@ -3,7 +3,7 @@ module Einhorn::Event
3
3
  include Persistent
4
4
 
5
5
  def self.open(server)
6
- self.new(server)
6
+ new(server)
7
7
  end
8
8
 
9
9
  def initialize(server)
@@ -15,14 +15,12 @@ module Einhorn::Event
15
15
  end
16
16
 
17
17
  def notify_readable
18
- begin
19
- while true
20
- return if @closed
21
- sock = Einhorn::Compat.accept_nonblock(@server)
22
- Connection.open(sock)
23
- end
24
- rescue Errno::EAGAIN
18
+ loop do
19
+ return if @closed
20
+ sock = Einhorn::Compat.accept_nonblock(@server)
21
+ Connection.open(sock)
25
22
  end
23
+ rescue Errno::EAGAIN
26
24
  end
27
25
 
28
26
  def to_io
@@ -30,7 +28,7 @@ module Einhorn::Event
30
28
  end
31
29
 
32
30
  def to_state
33
- {:class => self.class.to_s, :server => @server.fileno}
31
+ {class: self.class.to_s, server: @server.fileno}
34
32
  end
35
33
 
36
34
  def self.from_state(state)
@@ -11,8 +11,6 @@ module Einhorn::Event
11
11
  split = @read_buffer.split("\n", 2)
12
12
  if split.length > 1
13
13
  split
14
- else
15
- nil
16
14
  end
17
15
  end
18
16
 
@@ -21,7 +19,7 @@ module Einhorn::Event
21
19
  end
22
20
 
23
21
  def to_state
24
- state = {:class => self.class.to_s, :socket => @socket.fileno}
22
+ state = {class: self.class.to_s, socket: @socket.fileno}
25
23
  # Don't include by default because it's not that pretty
26
24
  state[:read_buffer] = @read_buffer if @read_buffer.length > 0
27
25
  state[:write_buffer] = @write_buffer if @write_buffer.length > 0
@@ -1,6 +1,7 @@
1
1
  # TODO: set lots of cloexecs
2
2
  module Einhorn::Event
3
3
  class LoopBreaker < AbstractTextDescriptor
4
- def consume_record(record); end
4
+ def consume_record(record)
5
+ end
5
6
  end
6
7
  end
@@ -8,7 +8,7 @@ module Einhorn::Event
8
8
 
9
9
  def self.from_state(state)
10
10
  klass_name = state[:class]
11
- if klass = @@persistent[klass_name]
11
+ if (klass = @@persistent[klass_name])
12
12
  klass.from_state(state)
13
13
  else
14
14
  Einhorn.log_error("Unrecognized persistent descriptor class #{klass_name.inspect}. Ignoring. This most likely indicates that your Einhorn version has upgraded. Everything should still be working, but it may be worth a restart.", :upgrade)
@@ -17,7 +17,7 @@ module Einhorn::Event
17
17
  end
18
18
 
19
19
  def self.persistent?(descriptor)
20
- @@persistent.values.any? {|klass| descriptor.kind_of?(klass)}
20
+ @@persistent.values.any? { |klass| descriptor.is_a?(klass) }
21
21
  end
22
22
  end
23
23
  end
@@ -2,7 +2,7 @@ module Einhorn::Event
2
2
  class Timer
3
3
  attr_reader :time
4
4
 
5
- def initialize(time, start=nil, &blk)
5
+ def initialize(time, start = nil, &blk)
6
6
  @time = time
7
7
  @start = start || Time.now
8
8
  @blk = blk
@@ -10,7 +10,7 @@ module Einhorn::Event
10
10
 
11
11
  # TODO: abstract into some interface
12
12
  def self.open(*args, &blk)
13
- instance = self.new(*args, &blk)
13
+ instance = new(*args, &blk)
14
14
  instance.register!
15
15
  instance
16
16
  end
@@ -27,12 +27,12 @@ module Einhorn::Event
27
27
  end
28
28
 
29
29
  def register!
30
- Einhorn.log_debug("Scheduling a new #{self.time}s timer")
30
+ Einhorn.log_debug("Scheduling a new #{time}s timer")
31
31
  Einhorn::Event.register_timer(self)
32
32
  end
33
33
 
34
34
  def deregister!
35
- Einhorn.log_debug("Nuking timer that expired #{Time.now - self.expires_at}s ago")
35
+ Einhorn.log_debug("Nuking timer that expired #{Time.now - expires_at}s ago")
36
36
  Einhorn::Event.deregister_timer(self)
37
37
  end
38
38
  end
data/lib/einhorn/event.rb CHANGED
@@ -1,9 +1,10 @@
1
- require 'set'
1
+ require "set"
2
2
 
3
3
  module Einhorn
4
4
  module Event
5
5
  @@loopbreak_reader = nil
6
6
  @@loopbreak_writer = nil
7
+ @@default_timeout = nil
7
8
  @@signal_actions = []
8
9
  @@readable = {}
9
10
  @@writeable = {}
@@ -36,8 +37,8 @@ module Einhorn
36
37
 
37
38
  def self.persistent_descriptors
38
39
  descriptor_sets = @@readable.values + @@writeable.values + @@timers.values
39
- descriptors = descriptor_sets.inject {|a, b| a | b}
40
- descriptors.select {|descriptor| Einhorn::Event::Persistent.persistent?(descriptor)}
40
+ descriptors = descriptor_sets.inject { |a, b| a | b }
41
+ descriptors.select { |descriptor| Einhorn::Event::Persistent.persistent?(descriptor) }
41
42
  end
42
43
 
43
44
  def self.restore_persistent_descriptors(persistent_descriptors)
@@ -80,8 +81,8 @@ module Einhorn
80
81
 
81
82
  def self.writeable_fds
82
83
  writers = @@writeable.select do |io, writers|
83
- writers.any? {|writer| writer.write_pending?}
84
- end.map {|io, writers| io}
84
+ writers.any? { |writer| writer.write_pending? }
85
+ end.map { |io, writers| io }
85
86
  Einhorn.log_debug("Writeable fds are #{writers.inspect}")
86
87
  writers
87
88
  end
@@ -117,10 +118,10 @@ module Einhorn
117
118
 
118
119
  def self.timeout
119
120
  # (expires_at of the next timer) - now
120
- if expires_at = @@timers.keys.sort[0]
121
+ if (expires_at = @@timers.keys.min)
121
122
  expires_at - Time.now
122
123
  else
123
- nil
124
+ @@default_timeout
124
125
  end
125
126
  end
126
127
 
@@ -129,7 +130,7 @@ module Einhorn
129
130
  # handlers. Since it's just an array we push to/shift from, we
130
131
  # can be sure there's no race (such as adding hash keys during
131
132
  # iteration.)
132
- while blk = @@signal_actions.shift
133
+ while (blk = @@signal_actions.shift)
133
134
  blk.call
134
135
  end
135
136
  end
@@ -142,37 +143,45 @@ module Einhorn
142
143
 
143
144
  readable, writeable, _ = IO.select(readable_fds, writeable_fds, nil, time)
144
145
  (readable || []).each do |io|
145
- @@readable[io].each {|reader| reader.notify_readable}
146
+ @@readable[io].each { |reader| reader.notify_readable }
146
147
  end
147
148
 
148
149
  (writeable || []).each do |io|
149
- @@writeable[io].each {|writer| writer.notify_writeable}
150
+ @@writeable[io].each { |writer| writer.notify_writeable }
150
151
  end
151
152
  end
152
153
 
153
154
  def self.run_timers
154
- @@timers.select {|expires_at, _| expires_at <= Time.now}.each do |expires_at, timers|
155
+ @@timers.select { |expires_at, _| expires_at <= Time.now }.each do |expires_at, timers|
155
156
  # Going to be modifying the set, so let's dup it.
156
- timers.dup.each {|timer| timer.ring!}
157
+ timers.dup.each { |timer| timer.ring! }
157
158
  end
158
159
  end
159
160
 
160
161
  def self.break_loop
161
162
  Einhorn.log_debug("Breaking the loop")
162
163
  begin
163
- @@loopbreak_writer.write_nonblock('a')
164
+ @@loopbreak_writer.write_nonblock("a")
164
165
  rescue Errno::EWOULDBLOCK, Errno::EAGAIN
165
166
  Einhorn.log_error("Loop break pipe is full -- probably means that we are quite backlogged")
166
167
  end
167
168
  end
169
+
170
+ def self.default_timeout=(val)
171
+ @@default_timeout = val.to_i == 0 ? nil : val.to_i
172
+ end
173
+
174
+ def self.default_timeout
175
+ @@default_timeout
176
+ end
168
177
  end
169
178
  end
170
179
 
171
- require 'einhorn/event/persistent'
172
- require 'einhorn/event/timer'
180
+ require "einhorn/event/persistent"
181
+ require "einhorn/event/timer"
173
182
 
174
- require 'einhorn/event/abstract_text_descriptor'
175
- require 'einhorn/event/ack_timer'
176
- require 'einhorn/event/command_server'
177
- require 'einhorn/event/connection'
178
- require 'einhorn/event/loop_breaker'
183
+ require "einhorn/event/abstract_text_descriptor"
184
+ require "einhorn/event/ack_timer"
185
+ require "einhorn/event/command_server"
186
+ require "einhorn/event/connection"
187
+ require "einhorn/event/loop_breaker"
@@ -0,0 +1,26 @@
1
+ module Einhorn
2
+ class PrctlAbstract
3
+ def self.get_pdeathsig
4
+ raise NotImplementedError
5
+ end
6
+
7
+ def self.set_pdeathsig(signal)
8
+ raise NotImplementedError
9
+ end
10
+ end
11
+
12
+ class PrctlUnimplemented < PrctlAbstract
13
+ # Deliberately empty; NotImplementedError is intended
14
+ end
15
+
16
+ if RUBY_PLATFORM.match?(/linux/)
17
+ begin
18
+ require "einhorn/prctl_linux"
19
+ Prctl = PrctlLinux
20
+ rescue LoadError
21
+ Prctl = PrctlUnimplemented
22
+ end
23
+ else
24
+ Prctl = PrctlUnimplemented
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ require "fiddle"
2
+ require "fiddle/import"
3
+
4
+ module Einhorn
5
+ module PrctlRaw
6
+ extend Fiddle::Importer
7
+ dlload Fiddle.dlopen(nil) # libc
8
+ extern "int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long)"
9
+
10
+ # From linux/prctl.h
11
+ SET_PDEATHSIG = 1
12
+ GET_PDEATHSIG = 2
13
+ end
14
+
15
+ class PrctlLinux < PrctlAbstract
16
+ # Reading integers is hard with fiddle. :(
17
+ IntStruct = Fiddle::CStructBuilder.create(Fiddle::CStruct, [Fiddle::TYPE_INT], ["i"])
18
+
19
+ def self.get_pdeathsig
20
+ out = IntStruct.malloc
21
+ out.i = 0
22
+ if PrctlRaw.prctl(PrctlRaw::GET_PDEATHSIG, out.to_i, 0, 0, 0) != 0
23
+ raise SystemCallError.new("get_pdeathsig", Fiddle.last_error)
24
+ end
25
+
26
+ signo = out.i
27
+ if signo == 0
28
+ return nil
29
+ end
30
+
31
+ Signal.signame(signo)
32
+ end
33
+
34
+ def self.set_pdeathsig(signal)
35
+ signo = if signal.nil?
36
+ 0
37
+ elsif signal.instance_of?(String)
38
+ Signal.list.fetch(signal)
39
+ else
40
+ signal
41
+ end
42
+
43
+ if PrctlRaw.prctl(PrctlRaw::SET_PDEATHSIG, signo, 0, 0, 0) != 0
44
+ raise SystemCallError.new("set_pdeathsig(#{signal})", Fiddle.last_error)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ require "yaml"
2
+
3
+ module Einhorn
4
+ module SafeYAML
5
+ begin
6
+ YAML.safe_load("---", permitted_classes: [])
7
+ rescue ArgumentError
8
+ def self.load(payload)
9
+ YAML.safe_load(payload, [Set, Symbol, Time], [], true)
10
+ end
11
+ else
12
+ def self.load(payload) # rubocop:disable Lint/DuplicateMethods
13
+ YAML.safe_load(payload, permitted_classes: [Set, Symbol, Time], aliases: true)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Einhorn
2
- VERSION = '0.7.4'
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,23 +1,21 @@
1
- require 'einhorn/client'
2
- require 'einhorn/command/interface'
1
+ require "einhorn/client"
2
+ require "einhorn/command/interface"
3
3
 
4
4
  module Einhorn
5
5
  module Worker
6
6
  class WorkerError < RuntimeError; end
7
7
 
8
8
  def self.is_worker?
9
- begin
10
- ensure_worker!
11
- rescue WorkerError
12
- false
13
- else
14
- true
15
- end
9
+ ensure_worker!
10
+ rescue WorkerError
11
+ false
12
+ else
13
+ true
16
14
  end
17
15
 
18
16
  def self.ensure_worker!
19
17
  # Make sure that EINHORN_MASTER_PID is my parent
20
- if ppid_s = ENV['EINHORN_MASTER_PID']
18
+ if (ppid_s = ENV["EINHORN_MASTER_PID"])
21
19
  ppid = ppid_s.to_i
22
20
  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
23
21
  true
@@ -27,10 +25,8 @@ module Einhorn
27
25
  end
28
26
 
29
27
  def self.ack(*args)
30
- begin
31
- ack!(*args)
32
- rescue WorkerError
33
- end
28
+ ack!(*args)
29
+ rescue WorkerError
34
30
  end
35
31
 
36
32
  # Returns the index of this Einhorn child process.
@@ -42,7 +38,7 @@ module Einhorn
42
38
  # Returns nil if not running in Einhorn, or running on a version
43
39
  # of Einhorn that does not support indexing children.
44
40
  def self.einhorn_child_index
45
- index = ENV['EINHORN_CHILD_INDEX']
41
+ index = ENV["EINHORN_CHILD_INDEX"]
46
42
  if index.nil? || index !~ /\A \d+ \z/x
47
43
  index
48
44
  else
@@ -65,45 +61,40 @@ module Einhorn
65
61
  # TODO: add a :fileno option? Easy to implement; not sure if it'd
66
62
  # be useful for anything. Maybe if it's always fd 3, because then
67
63
  # the user wouldn't have to provide an arg.
68
- def self.ack!(discovery=:env, arg=nil)
69
- ensure_worker!
70
- close_after_use = true
71
-
72
- case discovery
73
- when :env
74
- socket = ENV['EINHORN_SOCK_PATH']
75
- client = Einhorn::Client.for_path(socket)
76
- when :fd
77
- raise "No EINHORN_SOCK_FD provided in environment. Did you run einhorn with the -g flag?" unless fd_str = ENV['EINHORN_SOCK_FD']
78
-
79
- fd = Integer(fd_str)
80
- client = Einhorn::Client.for_fd(fd)
81
- close_after_use = false if arg
82
- when :direct
83
- socket = arg
84
- client = Einhorn::Client.for_path(socket)
85
- else
86
- raise "Unrecognized socket discovery mechanism: #{discovery.inspect}. Must be one of :filesystem, :argv, or :direct"
64
+ def self.ack!(discovery = :env, arg = nil)
65
+ handle_command_socket(discovery, arg) do |client|
66
+ client.send_command("command" => "worker:ack", "pid" => $$)
87
67
  end
68
+ end
88
69
 
89
- client.send_command({
90
- 'command' => 'worker:ack',
91
- 'pid' => $$
92
- })
93
-
94
- client.close if close_after_use
95
- true
70
+ # Call this to indicate your child process is up and in a healthy state.
71
+ # Arguments:
72
+ #
73
+ # @request_id: Identifies the request ID of the worker, can be used to debug wedged workers.
74
+ #
75
+ # @discovery: How to discover the master process's command socket.
76
+ # :env: Discover the path from ENV['EINHORN_SOCK_PATH']
77
+ # :fd: Just use the file descriptor in ENV['EINHORN_SOCK_FD'].
78
+ # Must run the master with the -g flag. This is mostly
79
+ # useful if you don't have a nice library like Einhorn::Worker.
80
+ # Then @arg being true causes the FD to be left open after ACK;
81
+ # otherwise it is closed.
82
+ # :direct: Provide the path to the command socket in @arg.
83
+ def self.ping!(request_id, discovery = :env, arg = nil)
84
+ handle_command_socket(discovery, arg) do |client|
85
+ client.send_command("command" => "worker:ping", "pid" => $$, "request_id" => request_id)
86
+ end
96
87
  end
97
88
 
98
- def self.socket(number=nil)
89
+ def self.socket(number = nil)
99
90
  number ||= 0
100
91
  einhorn_fd(number)
101
92
  end
102
93
 
103
- def self.socket!(number=nil)
94
+ def self.socket!(number = nil)
104
95
  number ||= 0
105
96
 
106
- unless count = einhorn_fd_count
97
+ unless (count = einhorn_fd_count)
107
98
  raise "No EINHORN_FD_COUNT provided in environment. Are you running under Einhorn?"
108
99
  end
109
100
 
@@ -111,7 +102,7 @@ module Einhorn
111
102
  raise "Only #{count} FDs available, but FD #{number} was requested"
112
103
  end
113
104
 
114
- unless fd = einhorn_fd(number)
105
+ unless (fd = einhorn_fd(number))
115
106
  raise "No EINHORN_FD_#{number} provided in environment. That's pretty weird"
116
107
  end
117
108
 
@@ -119,14 +110,14 @@ module Einhorn
119
110
  end
120
111
 
121
112
  def self.einhorn_fd(n)
122
- unless raw_fd = ENV["EINHORN_FD_#{n}"]
113
+ unless (raw_fd = ENV["EINHORN_FD_#{n}"])
123
114
  return nil
124
115
  end
125
116
  Integer(raw_fd)
126
117
  end
127
118
 
128
119
  def self.einhorn_fd_count
129
- unless raw_count = ENV['EINHORN_FD_COUNT']
120
+ unless (raw_count = ENV["EINHORN_FD_COUNT"])
130
121
  return 0
131
122
  end
132
123
  Integer(raw_count)
@@ -134,15 +125,42 @@ module Einhorn
134
125
 
135
126
  # Call this to handle graceful shutdown requests to your app.
136
127
  def self.graceful_shutdown(&blk)
137
- Signal.trap('USR2', &blk)
128
+ Signal.trap("USR2", &blk)
138
129
  end
139
130
 
140
- private
131
+ def self.handle_command_socket(discovery, contextual_arg)
132
+ ensure_worker!
133
+ close_after_use = true
134
+
135
+ case discovery
136
+ when :env
137
+ socket = ENV["EINHORN_SOCK_PATH"]
138
+ client = Einhorn::Client.for_path(socket)
139
+ when :fd
140
+ raise "No EINHORN_SOCK_FD provided in environment. Did you run einhorn with the -g flag?" unless (fd_str = ENV["EINHORN_SOCK_FD"])
141
+
142
+ fd = Integer(fd_str)
143
+ client = Einhorn::Client.for_fd(fd)
144
+ close_after_use = false if contextual_arg
145
+ when :direct
146
+ socket = contextual_arg
147
+ client = Einhorn::Client.for_path(socket)
148
+ else
149
+ raise "Unrecognized socket discovery mechanism: #{discovery.inspect}. Must be one of :filesystem, :argv, or :direct"
150
+ end
151
+
152
+ yield client
153
+ client.close if close_after_use
154
+
155
+ true
156
+ end
157
+ private_class_method :handle_command_socket
141
158
 
142
159
  def self.socket_from_filesystem(cmd_name)
143
160
  ppid = Process.ppid
144
161
  socket_path_file = Einhorn::Command::Interface.socket_path_file(ppid)
145
162
  File.read(socket_path_file)
146
163
  end
164
+ private_class_method :socket_from_filesystem
147
165
  end
148
166
  end
@@ -7,13 +7,13 @@ module Einhorn
7
7
  end
8
8
 
9
9
  def self.workers
10
- workers_with_state.map {|pid, _| pid}
10
+ workers_with_state.map { |pid, _| pid }
11
11
  end
12
12
 
13
13
  def self.unsignaled_workers
14
14
  workers_with_state.select do |pid, spec|
15
15
  spec[:signaled].length == 0
16
- end.map {|pid, _| pid}
16
+ end.map { |pid, _| pid }
17
17
  end
18
18
 
19
19
  def self.modern_workers_with_state
@@ -23,15 +23,15 @@ module Einhorn
23
23
  end
24
24
 
25
25
  def self.acked_modern_workers_with_state
26
- modern_workers_with_state.select {|pid, spec| spec[:acked]}
26
+ modern_workers_with_state.select { |pid, spec| spec[:acked] }
27
27
  end
28
28
 
29
29
  def self.modern_workers
30
- modern_workers_with_state.map {|pid, _| pid}
30
+ modern_workers_with_state.map { |pid, _| pid }
31
31
  end
32
32
 
33
33
  def self.acked_modern_workers
34
- acked_modern_workers_with_state.map {|pid, _| pid}
34
+ acked_modern_workers_with_state.map { |pid, _| pid }
35
35
  end
36
36
 
37
37
  def self.unsignaled_modern_workers_with_state
@@ -43,23 +43,23 @@ module Einhorn
43
43
  def self.acked_unsignaled_modern_workers
44
44
  acked_modern_workers_with_state.select do |_, spec|
45
45
  spec[:signaled].length == 0
46
- end.map {|pid, _| pid}
46
+ end.map { |pid, _| pid }
47
47
  end
48
48
 
49
49
  def self.unsignaled_modern_workers_with_priority
50
50
  unsignaled_modern_workers_with_state.sort_by do |pid, spec|
51
51
  spec[:acked] ? 1 : 0
52
- end.map {|pid, _| pid}
52
+ end.map { |pid, _| pid }
53
53
  end
54
54
 
55
55
  def self.unacked_unsignaled_modern_workers_with_state
56
- modern_workers_with_state.select {|pid, spec|
56
+ modern_workers_with_state.select { |pid, spec|
57
57
  !spec[:acked] && spec[:signaled].length == 0
58
58
  }
59
59
  end
60
60
 
61
61
  def self.unacked_unsignaled_modern_workers
62
- unacked_unsignaled_modern_workers_with_state.map {|pid, _| pid}
62
+ unacked_unsignaled_modern_workers_with_state.map { |pid, _| pid }
63
63
  end
64
64
 
65
65
  # Use the number of modern workers, rather than unsignaled modern