einhorn 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/README.md +2 -5
- data/example/thin_example +5 -5
- data/lib/einhorn/command.rb +34 -5
- data/lib/einhorn/command/interface.rb +15 -0
- data/lib/einhorn/version.rb +1 -1
- data/lib/einhorn/worker.rb +17 -0
- metadata +4 -9
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -238,11 +238,8 @@ servers) to a wider array of applications.
|
|
238
238
|
See https://stripe.com/blog/meet-einhorn for more background.
|
239
239
|
|
240
240
|
Stripe currently uses Einhorn in production for a number of
|
241
|
-
services.
|
242
|
-
|
243
|
-
can obtain these patches from our public forks of the
|
244
|
-
[respective](https://github.com/stripe/thin)
|
245
|
-
[projects](https://github.com/stripe/eventmachine). Check out
|
241
|
+
services. You can use Conrad Irwin's thin-attach_socket gem along with
|
242
|
+
EventMachine-LE to support file-descriptor passing. Check out
|
246
243
|
`example/thin_example` for an example of running Thin under Einhorn.
|
247
244
|
|
248
245
|
## Compatibility
|
data/example/thin_example
CHANGED
@@ -9,11 +9,9 @@
|
|
9
9
|
require 'rubygems'
|
10
10
|
require 'einhorn'
|
11
11
|
|
12
|
-
|
13
|
-
gem 'thin', '1.3.2.stripe.0'
|
14
|
-
gem 'eventmachine', '1.0.0.beta.4.stripe.0'
|
15
|
-
|
12
|
+
require 'eventmachine-le'
|
16
13
|
require 'thin'
|
14
|
+
require 'thin/attach_socket'
|
17
15
|
|
18
16
|
class App
|
19
17
|
def initialize(id)
|
@@ -42,7 +40,9 @@ def einhorn_main
|
|
42
40
|
EventMachine.run do
|
43
41
|
(0...fd_count).each do |i|
|
44
42
|
sock = Einhorn::Worker.socket!(i)
|
45
|
-
srv = Thin::Server.new(
|
43
|
+
srv = Thin::Server.new(App.new(i),
|
44
|
+
:backend => Thin::Backends::AttachSocket,
|
45
|
+
:socket => IO.for_fd(sock))
|
46
46
|
srv.start
|
47
47
|
end
|
48
48
|
end
|
data/lib/einhorn/command.rb
CHANGED
@@ -152,6 +152,24 @@ module Einhorn
|
|
152
152
|
output
|
153
153
|
end
|
154
154
|
|
155
|
+
def self.set_workers(new)
|
156
|
+
if new == Einhorn::State.config[:number]
|
157
|
+
return ""
|
158
|
+
end
|
159
|
+
|
160
|
+
Einhorn::Event.break_loop
|
161
|
+
old = Einhorn::State.config[:number]
|
162
|
+
Einhorn::State.config[:number] = new
|
163
|
+
output = "Altering worker count, #{old} -> #{new}. Will "
|
164
|
+
if old < new
|
165
|
+
output << "spin up additional workers."
|
166
|
+
else
|
167
|
+
output << "gracefully terminate workers."
|
168
|
+
end
|
169
|
+
$stderr.puts(output)
|
170
|
+
output
|
171
|
+
end
|
172
|
+
|
155
173
|
def self.dumpable_state
|
156
174
|
global_state = Einhorn::State.state
|
157
175
|
descriptor_state = Einhorn::Event.persistent_descriptors.map do |descriptor|
|
@@ -220,8 +238,16 @@ module Einhorn
|
|
220
238
|
end
|
221
239
|
end
|
222
240
|
|
241
|
+
def self.next_index
|
242
|
+
all_indexes = Set.new(Einhorn::State.children.map { |k, st| st[:index] })
|
243
|
+
0.upto(all_indexes.length) do |i|
|
244
|
+
return i unless all_indexes.include?(i)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
223
248
|
def self.spinup(cmd=nil)
|
224
249
|
cmd ||= Einhorn::State.cmd
|
250
|
+
index = next_index
|
225
251
|
if Einhorn::TransientState.preloaded
|
226
252
|
pid = fork do
|
227
253
|
Einhorn::TransientState.whatami = :worker
|
@@ -234,7 +260,7 @@ module Einhorn
|
|
234
260
|
|
235
261
|
reseed_random
|
236
262
|
|
237
|
-
prepare_child_environment
|
263
|
+
prepare_child_environment(index)
|
238
264
|
einhorn_main
|
239
265
|
end
|
240
266
|
else
|
@@ -251,17 +277,18 @@ module Einhorn
|
|
251
277
|
# Note that Ruby 1.9's close_others option is useful here.
|
252
278
|
Einhorn::Event.close_all_for_worker
|
253
279
|
|
254
|
-
prepare_child_environment
|
280
|
+
prepare_child_environment(index)
|
255
281
|
Einhorn::Compat.exec(cmd[0], cmd[1..-1], :close_others => false)
|
256
282
|
end
|
257
283
|
end
|
258
284
|
|
259
|
-
Einhorn.log_info("===> Launched #{pid}", :upgrade)
|
285
|
+
Einhorn.log_info("===> Launched #{pid} (index: #{index})", :upgrade)
|
260
286
|
Einhorn::State.children[pid] = {
|
261
287
|
:type => :worker,
|
262
288
|
:version => Einhorn::State.version,
|
263
289
|
:acked => false,
|
264
|
-
:signaled => Set.new
|
290
|
+
:signaled => Set.new,
|
291
|
+
:index => index
|
265
292
|
}
|
266
293
|
Einhorn::State.last_spinup = Time.now
|
267
294
|
|
@@ -276,7 +303,7 @@ module Einhorn
|
|
276
303
|
end
|
277
304
|
end
|
278
305
|
|
279
|
-
def self.prepare_child_environment
|
306
|
+
def self.prepare_child_environment(index)
|
280
307
|
# This is run from the child
|
281
308
|
ENV['EINHORN_MASTER_PID'] = Process.ppid.to_s
|
282
309
|
ENV['EINHORN_SOCK_PATH'] = Einhorn::Command::Interface.socket_path
|
@@ -289,6 +316,8 @@ module Einhorn
|
|
289
316
|
ENV['EINHORN_FD_COUNT'] = Einhorn::State.bind_fds.length.to_s
|
290
317
|
Einhorn::State.bind_fds.each_with_index {|fd, i| ENV["EINHORN_FD_#{i}"] = fd.to_s}
|
291
318
|
|
319
|
+
ENV['EINHORN_CHILD_INDEX'] = index.to_s
|
320
|
+
|
292
321
|
# EINHORN_FDS is deprecated. It was originally an attempt to
|
293
322
|
# match Upstart's nominal internal support for space-separated
|
294
323
|
# FD lists, but nobody uses that in practice, and it makes
|
@@ -328,6 +328,21 @@ EOF
|
|
328
328
|
Einhorn::Command.decrement
|
329
329
|
end
|
330
330
|
|
331
|
+
command 'set_workers', 'Set the number of Einhorn child processes' do |conn, request|
|
332
|
+
args = request['args']
|
333
|
+
if message = validate_args(args)
|
334
|
+
next message
|
335
|
+
end
|
336
|
+
|
337
|
+
count = args[0].to_i
|
338
|
+
if count < 1 || count > 100
|
339
|
+
# sancheck. 100 is kinda arbitrary.
|
340
|
+
next "Invalid count: '#{args[0]}'. Must be an integer in [1,100)."
|
341
|
+
end
|
342
|
+
|
343
|
+
Einhorn::Command.set_workers(count)
|
344
|
+
end
|
345
|
+
|
331
346
|
command 'quieter', 'Decrease verbosity' do
|
332
347
|
Einhorn::Command.quieter
|
333
348
|
end
|
data/lib/einhorn/version.rb
CHANGED
data/lib/einhorn/worker.rb
CHANGED
@@ -33,6 +33,23 @@ module Einhorn
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# Returns the index of this Einhorn child process.
|
37
|
+
#
|
38
|
+
# If an Einhorn master has N children, this will be an integer in
|
39
|
+
# the range [0,N), and no two workers running concurrently will
|
40
|
+
# ever have the same index.
|
41
|
+
#
|
42
|
+
# Returns nil if not running in Einhorn, or running on a version
|
43
|
+
# of Einhorn that does not support indexing children.
|
44
|
+
def self.einhorn_child_index
|
45
|
+
index = ENV['EINHORN_CHILD_INDEX']
|
46
|
+
if index.nil? || index !~ /\A \d+ \z/x
|
47
|
+
index
|
48
|
+
else
|
49
|
+
index.to_i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
36
53
|
# Call this once your app is up and running in a good state.
|
37
54
|
# Arguments:
|
38
55
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: einhorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-04-
|
12
|
+
date: 2014-04-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -164,21 +164,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
164
|
- - ! '>='
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
|
-
segments:
|
168
|
-
- 0
|
169
|
-
hash: -2873954184645788574
|
170
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
168
|
none: false
|
172
169
|
requirements:
|
173
170
|
- - ! '>='
|
174
171
|
- !ruby/object:Gem::Version
|
175
172
|
version: '0'
|
176
|
-
segments:
|
177
|
-
- 0
|
178
|
-
hash: -2873954184645788574
|
179
173
|
requirements: []
|
180
174
|
rubyforge_project:
|
181
|
-
rubygems_version: 1.8.23
|
175
|
+
rubygems_version: 1.8.23.2
|
182
176
|
signing_key:
|
183
177
|
specification_version: 3
|
184
178
|
summary: ! 'Einhorn: the language-independent shared socket manager'
|
@@ -190,3 +184,4 @@ test_files:
|
|
190
184
|
- test/unit/einhorn/command/interface.rb
|
191
185
|
- test/unit/einhorn/event.rb
|
192
186
|
- test/unit/einhorn/worker_pool.rb
|
187
|
+
has_rdoc:
|