einhorn 0.4.8 → 0.4.9
Sign up to get free protection for your applications and to get access to all the features.
- data/einhorn.gemspec +1 -0
- data/example/plugin.rb +14 -4
- data/lib/einhorn.rb +23 -4
- data/lib/einhorn/command.rb +6 -1
- data/lib/einhorn/version.rb +1 -1
- data/test/unit/einhorn.rb +3 -3
- metadata +5 -3
data/einhorn.gemspec
CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.summary = "Einhorn: the language-independent shared socket manager"
|
8
8
|
gem.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."
|
9
9
|
gem.homepage = "https://github.com/stripe/einhorn"
|
10
|
+
gem.license = "MIT"
|
10
11
|
|
11
12
|
gem.files = `git ls-files`.split($\)
|
12
13
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/example/plugin.rb
CHANGED
@@ -8,6 +8,17 @@
|
|
8
8
|
|
9
9
|
module Einhorn::Plugins
|
10
10
|
module ExamplePlugin
|
11
|
+
# If a State module is defined, its contents will be passed to new
|
12
|
+
# einhorn processes when einhorn is reloaded
|
13
|
+
module State
|
14
|
+
extend Einhorn::AbstractState
|
15
|
+
def self.default_state
|
16
|
+
{
|
17
|
+
:yay => nil
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
def self.initialize_example_plugin
|
12
23
|
# The initializer method must be named `initialize_##[plugin_name]',
|
13
24
|
# where [plugin_name] is the name of the plugin module or class in
|
@@ -16,16 +27,15 @@ module Einhorn::Plugins
|
|
16
27
|
end
|
17
28
|
|
18
29
|
def self.optparse(opts)
|
19
|
-
@options = {}
|
20
30
|
opts.on("--my-option X", "Patch einhorn with additional options!") do |x|
|
21
|
-
|
31
|
+
State.yay = x
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
25
35
|
def self.post_optparse
|
26
36
|
# Called after all options native to einhorn or patched by any plugins
|
27
|
-
# are parsed.
|
28
|
-
|
37
|
+
# are parsed. Good place to do argument validation
|
38
|
+
raise "Argument --my-option is required" unless State.yay
|
29
39
|
end
|
30
40
|
|
31
41
|
def self.event_loop
|
data/lib/einhorn.rb
CHANGED
@@ -93,19 +93,21 @@ module Einhorn
|
|
93
93
|
|
94
94
|
def self.restore_state(state)
|
95
95
|
parsed = YAML.load(state)
|
96
|
-
updated_state, message = update_state(parsed[:state])
|
96
|
+
updated_state, message = update_state(Einhorn::State, "einhorn", parsed[:state])
|
97
97
|
Einhorn::State.state = updated_state
|
98
98
|
Einhorn::Event.restore_persistent_descriptors(parsed[:persistent_descriptors])
|
99
|
+
plugin_messages = update_plugin_states(parsed[:plugins])
|
99
100
|
# Do this after setting state so verbosity is right
|
100
101
|
Einhorn.log_info("Using loaded state: #{parsed.inspect}")
|
101
102
|
Einhorn.log_info(message) if message
|
103
|
+
plugin_messages.each {|msg| Einhorn.log_info(msg)}
|
102
104
|
end
|
103
105
|
|
104
|
-
def self.update_state(old_state)
|
106
|
+
def self.update_state(store, store_name, old_state)
|
105
107
|
# TODO: handle format updates somehow? (probably need to write
|
106
108
|
# special-case code for each)
|
107
109
|
updated_state = old_state.dup
|
108
|
-
default =
|
110
|
+
default = store.default_state
|
109
111
|
added_keys = default.keys - old_state.keys
|
110
112
|
deleted_keys = old_state.keys - default.keys
|
111
113
|
return [updated_state, nil] if added_keys.length == 0 && deleted_keys.length == 0
|
@@ -116,12 +118,29 @@ module Einhorn
|
|
116
118
|
message = []
|
117
119
|
message << "adding default values for #{added_keys.inspect}"
|
118
120
|
message << "deleting values for #{deleted_keys.inspect}"
|
119
|
-
message = "State format has changed: #{message.join(', ')}"
|
121
|
+
message = "State format for #{store_name} has changed: #{message.join(', ')}"
|
120
122
|
|
121
123
|
# Can't print yet, since state hasn't been set, so we pass along the message.
|
122
124
|
[updated_state, message]
|
123
125
|
end
|
124
126
|
|
127
|
+
def self.update_plugin_states(states)
|
128
|
+
plugin_messages = []
|
129
|
+
(states || {}).each do |name, plugin_state|
|
130
|
+
plugin = Einhorn.plugins[name]
|
131
|
+
unless plugin && plugin.const_defined?(:State)
|
132
|
+
plugin_messages << "No state defined in this version of the #{name} " +
|
133
|
+
"plugin; dropping values for keys #{plugin_state.keys.inspect}"
|
134
|
+
next
|
135
|
+
end
|
136
|
+
|
137
|
+
updated_state, plugin_message = update_state(plugin::State, "plugin #{name}", plugin_state)
|
138
|
+
plugin_messages << plugin_message if plugin_message
|
139
|
+
plugin::State.state = updated_state
|
140
|
+
end
|
141
|
+
plugin_messages
|
142
|
+
end
|
143
|
+
|
125
144
|
def self.print_state
|
126
145
|
log_info(Einhorn::State.state.pretty_inspect)
|
127
146
|
end
|
data/lib/einhorn/command.rb
CHANGED
@@ -157,10 +157,15 @@ module Einhorn
|
|
157
157
|
descriptor_state = Einhorn::Event.persistent_descriptors.map do |descriptor|
|
158
158
|
descriptor.to_state
|
159
159
|
end
|
160
|
+
plugin_state = {}
|
161
|
+
Einhorn.plugins.each do |name, plugin|
|
162
|
+
plugin_state[name] = plugin::State.state if plugin.const_defined?(:State)
|
163
|
+
end
|
160
164
|
|
161
165
|
{
|
162
166
|
:state => global_state,
|
163
|
-
:persistent_descriptors => descriptor_state
|
167
|
+
:persistent_descriptors => descriptor_state,
|
168
|
+
:plugins => plugin_state
|
164
169
|
}
|
165
170
|
end
|
166
171
|
|
data/lib/einhorn/version.rb
CHANGED
data/test/unit/einhorn.rb
CHANGED
@@ -41,16 +41,16 @@ class EinhornTest < EinhornTestCase
|
|
41
41
|
Einhorn::State.stubs(:default_state).returns(:baz => 23, :foo => 1)
|
42
42
|
old_state = {:foo => 2, :bar => 2}
|
43
43
|
|
44
|
-
updated_state, message = Einhorn.update_state(old_state)
|
44
|
+
updated_state, message = Einhorn.update_state(Einhorn::State, 'einhorn', old_state)
|
45
45
|
assert_equal({:baz => 23, :foo => 2}, updated_state)
|
46
|
-
assert_match(/State format has changed/, message)
|
46
|
+
assert_match(/State format for einhorn has changed/, message)
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'does not change the state if the format has not changed' do
|
50
50
|
Einhorn::State.stubs(:default_state).returns(:baz => 23, :foo => 1)
|
51
51
|
old_state = {:baz => 14, :foo => 1234}
|
52
52
|
|
53
|
-
updated_state, message = Einhorn.update_state(old_state)
|
53
|
+
updated_state, message = Einhorn.update_state(Einhorn::State, 'einhorn', old_state)
|
54
54
|
assert_equal({:baz => 14, :foo => 1234}, updated_state)
|
55
55
|
assert(message.nil?)
|
56
56
|
end
|
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.4.
|
4
|
+
version: 0.4.9
|
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: 2013-
|
12
|
+
date: 2013-08-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -117,7 +117,8 @@ files:
|
|
117
117
|
- test/unit/einhorn/event.rb
|
118
118
|
- test/unit/einhorn/worker_pool.rb
|
119
119
|
homepage: https://github.com/stripe/einhorn
|
120
|
-
licenses:
|
120
|
+
licenses:
|
121
|
+
- MIT
|
121
122
|
post_install_message:
|
122
123
|
rdoc_options: []
|
123
124
|
require_paths:
|
@@ -148,3 +149,4 @@ test_files:
|
|
148
149
|
- test/unit/einhorn/command/interface.rb
|
149
150
|
- test/unit/einhorn/event.rb
|
150
151
|
- test/unit/einhorn/worker_pool.rb
|
152
|
+
has_rdoc:
|