einhorn 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +236 -0
- data/README.md.in +79 -0
- data/Rakefile +19 -0
- data/bin/einhorn +284 -0
- data/bin/einhornsh +120 -0
- data/einhorn.gemspec +21 -0
- data/example/pool_worker.rb +19 -0
- data/example/thin_example +52 -0
- data/example/time_server +48 -0
- data/lib/einhorn/client.rb +48 -0
- data/lib/einhorn/command/interface.rb +336 -0
- data/lib/einhorn/command.rb +336 -0
- data/lib/einhorn/event/abstract_text_descriptor.rb +132 -0
- data/lib/einhorn/event/ack_timer.rb +20 -0
- data/lib/einhorn/event/command_server.rb +58 -0
- data/lib/einhorn/event/connection.rb +45 -0
- data/lib/einhorn/event/loop_breaker.rb +6 -0
- data/lib/einhorn/event/persistent.rb +23 -0
- data/lib/einhorn/event/timer.rb +39 -0
- data/lib/einhorn/event.rb +150 -0
- data/lib/einhorn/version.rb +3 -0
- data/lib/einhorn/worker.rb +94 -0
- data/lib/einhorn/worker_pool.rb +56 -0
- data/lib/einhorn.rb +282 -0
- data/test/test_helper.rb +7 -0
- data/test/unit/einhorn/command/interface.rb +47 -0
- data/test/unit/einhorn/command.rb +21 -0
- data/test/unit/einhorn/event.rb +89 -0
- data/test/unit/einhorn.rb +38 -0
- metadata +143 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../test_helper'))
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'einhorn'
|
5
|
+
|
6
|
+
module Einhorn::Event
|
7
|
+
def self.reset
|
8
|
+
@@loopbreak_reader = nil
|
9
|
+
@@loopbreak_writer = nil
|
10
|
+
@@readable = {}
|
11
|
+
@@writeable = {}
|
12
|
+
@@timers = {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class EventTest < Test::Unit::TestCase
|
17
|
+
context "when run the event loop" do
|
18
|
+
setup do
|
19
|
+
Einhorn::Event.reset
|
20
|
+
end
|
21
|
+
|
22
|
+
teardown do
|
23
|
+
Einhorn::Event.reset
|
24
|
+
end
|
25
|
+
|
26
|
+
should "select on readable descriptors" do
|
27
|
+
sock1 = mock(:fileno => 4)
|
28
|
+
sock2 = mock(:fileno => 5)
|
29
|
+
|
30
|
+
conn1 = Einhorn::Event::Connection.open(sock1)
|
31
|
+
conn2 = Einhorn::Event::Connection.open(sock2)
|
32
|
+
|
33
|
+
IO.expects(:select).once.with do |readers, writers, errs, timeout|
|
34
|
+
Set.new(readers) == Set.new([sock1, sock2]) &&
|
35
|
+
writers == [] &&
|
36
|
+
errs == nil &&
|
37
|
+
timeout == nil
|
38
|
+
end.returns([[], [], []])
|
39
|
+
|
40
|
+
Einhorn::Event.loop_once
|
41
|
+
end
|
42
|
+
|
43
|
+
should "select on writeable descriptors" do
|
44
|
+
sock1 = mock(:fileno => 4)
|
45
|
+
sock2 = mock(:fileno => 5)
|
46
|
+
|
47
|
+
conn1 = Einhorn::Event::Connection.open(sock1)
|
48
|
+
conn2 = Einhorn::Event::Connection.open(sock2)
|
49
|
+
|
50
|
+
sock2.expects(:write_nonblock).once.raises(Errno::EWOULDBLOCK.new)
|
51
|
+
conn2.write('Hello!')
|
52
|
+
|
53
|
+
IO.expects(:select).once.with do |readers, writers, errs, timeout|
|
54
|
+
Set.new(readers) == Set.new([sock1, sock2]) &&
|
55
|
+
writers == [sock2] &&
|
56
|
+
errs == nil &&
|
57
|
+
timeout == nil
|
58
|
+
end.returns([[], [], []])
|
59
|
+
|
60
|
+
Einhorn::Event.loop_once
|
61
|
+
end
|
62
|
+
|
63
|
+
should "run callbacks for ready selectables" do
|
64
|
+
sock1 = mock(:fileno => 4)
|
65
|
+
sock2 = mock(:fileno => 5)
|
66
|
+
|
67
|
+
conn1 = Einhorn::Event::Connection.open(sock1)
|
68
|
+
conn2 = Einhorn::Event::Connection.open(sock2)
|
69
|
+
|
70
|
+
sock2.expects(:write_nonblock).once.raises(Errno::EWOULDBLOCK.new)
|
71
|
+
conn2.write('Hello!')
|
72
|
+
|
73
|
+
IO.expects(:select).once.with do |readers, writers, errs, timeout|
|
74
|
+
Set.new(readers) == Set.new([sock1, sock2]) &&
|
75
|
+
writers == [sock2] &&
|
76
|
+
errs == nil &&
|
77
|
+
timeout == nil
|
78
|
+
end.returns([[sock1], [sock2], []])
|
79
|
+
|
80
|
+
conn1.expects(:notify_readable).once
|
81
|
+
conn2.expects(:notify_writeable).never
|
82
|
+
|
83
|
+
conn1.expects(:notify_readable).never
|
84
|
+
conn2.expects(:notify_writeable).once
|
85
|
+
|
86
|
+
Einhorn::Event.loop_once
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../test_helper'))
|
2
|
+
|
3
|
+
require 'einhorn'
|
4
|
+
|
5
|
+
class EinhornTest < Test::Unit::TestCase
|
6
|
+
context "when sockifying" do
|
7
|
+
teardown do
|
8
|
+
Einhorn::State.sockets = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
should "correctly parse srv: arguments" do
|
12
|
+
cmd = ['foo', 'srv:1.2.3.4:123,llama,test', 'bar']
|
13
|
+
Einhorn.expects(:bind).once.with('1.2.3.4', '123', ['llama', 'test']).returns(4)
|
14
|
+
|
15
|
+
Einhorn.socketify!(cmd)
|
16
|
+
|
17
|
+
assert_equal(['foo', '4', 'bar'], cmd)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "correctly parse --opt=srv: arguments" do
|
21
|
+
cmd = ['foo', '--opt=srv:1.2.3.4:456', 'baz']
|
22
|
+
Einhorn.expects(:bind).once.with('1.2.3.4', '456', []).returns(5)
|
23
|
+
|
24
|
+
Einhorn.socketify!(cmd)
|
25
|
+
|
26
|
+
assert_equal(['foo', '--opt=5', 'baz'], cmd)
|
27
|
+
end
|
28
|
+
|
29
|
+
should "use the same fd number for the same server spec" do
|
30
|
+
cmd = ['foo', '--opt=srv:1.2.3.4:8910', 'srv:1.2.3.4:8910']
|
31
|
+
Einhorn.expects(:bind).once.with('1.2.3.4', '8910', []).returns(10)
|
32
|
+
|
33
|
+
Einhorn.socketify!(cmd)
|
34
|
+
|
35
|
+
assert_equal(['foo', '--opt=10', '10'], cmd)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: einhorn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Greg Brockman
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-05-29 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: json
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: shoulda
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: mocha
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Einhorn makes it easy to run multiple instances of an application server, all listening on the same port. You can also seamlessly restart your workers without dropping any requests. Einhorn requires minimal application-level support, making it easy to use with an existing project.
|
63
|
+
email:
|
64
|
+
- gdb@stripe.com
|
65
|
+
executables:
|
66
|
+
- einhorn
|
67
|
+
- einhornsh
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .gitignore
|
74
|
+
- Gemfile
|
75
|
+
- LICENSE
|
76
|
+
- README.md
|
77
|
+
- README.md.in
|
78
|
+
- Rakefile
|
79
|
+
- bin/einhorn
|
80
|
+
- bin/einhornsh
|
81
|
+
- einhorn.gemspec
|
82
|
+
- example/pool_worker.rb
|
83
|
+
- example/thin_example
|
84
|
+
- example/time_server
|
85
|
+
- lib/einhorn.rb
|
86
|
+
- lib/einhorn/client.rb
|
87
|
+
- lib/einhorn/command.rb
|
88
|
+
- lib/einhorn/command/interface.rb
|
89
|
+
- lib/einhorn/event.rb
|
90
|
+
- lib/einhorn/event/abstract_text_descriptor.rb
|
91
|
+
- lib/einhorn/event/ack_timer.rb
|
92
|
+
- lib/einhorn/event/command_server.rb
|
93
|
+
- lib/einhorn/event/connection.rb
|
94
|
+
- lib/einhorn/event/loop_breaker.rb
|
95
|
+
- lib/einhorn/event/persistent.rb
|
96
|
+
- lib/einhorn/event/timer.rb
|
97
|
+
- lib/einhorn/version.rb
|
98
|
+
- lib/einhorn/worker.rb
|
99
|
+
- lib/einhorn/worker_pool.rb
|
100
|
+
- test/test_helper.rb
|
101
|
+
- test/unit/einhorn.rb
|
102
|
+
- test/unit/einhorn/command.rb
|
103
|
+
- test/unit/einhorn/command/interface.rb
|
104
|
+
- test/unit/einhorn/event.rb
|
105
|
+
homepage: https://github.com/stripe/einhorn
|
106
|
+
licenses: []
|
107
|
+
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 3
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
version: "0"
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
requirements: []
|
132
|
+
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 1.8.21
|
135
|
+
signing_key:
|
136
|
+
specification_version: 3
|
137
|
+
summary: "Einhorn: the language-independent shared socket manager"
|
138
|
+
test_files:
|
139
|
+
- test/test_helper.rb
|
140
|
+
- test/unit/einhorn.rb
|
141
|
+
- test/unit/einhorn/command.rb
|
142
|
+
- test/unit/einhorn/command/interface.rb
|
143
|
+
- test/unit/einhorn/event.rb
|