serverengine 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1c09d476bdc08a078882ba14ee74f487ab988a397d2228c3e83f611fff94df1
4
- data.tar.gz: 33732af3d1c591ec28c67249b1b67b16b142f80048f70c3cf5c769b3e267b76a
3
+ metadata.gz: 8b802588a6e93b69c2dc9810ab33b9e3195e14d93c5f977961a04cc6d88cacf1
4
+ data.tar.gz: 9921383ec5ae39cfe982da9ce8c0b432bbc553c2ea5d2090a2d849ec2500c230
5
5
  SHA512:
6
- metadata.gz: 383aaf8822f01aec3ce2e4a25243da8ca741da9d11f97c601c31cc6985e285743a088cafdd4fd918b58a966960376f65b28645b1fca74d0741e64052bd329ac8
7
- data.tar.gz: ca10bd75948760060c8ae433cb2021a7024d6b076d84157012db5ae6809d01c9a8bb2eb2bb1f9f8d84f0881e4cbaf3bebfb25ef959130574e0cf717550ee1867
6
+ metadata.gz: ea4c0e4b34490665e4287c0f43e4ea1f32c10fe022464a69326505ec21aad2650e53b842c2aaeec2a969d914f73715ee059b2bdbb3d72d14b0bce51192bf217c
7
+ data.tar.gz: 3e30810b08b8667f2295b41fca60c4683126d8936e32169d0789b8ec02ba3965fc631dbe069c9a8cf057e109ccaa9ad3ad14f4507b2388dcd9ae27463ce39651
data/Changelog CHANGED
@@ -1,3 +1,7 @@
1
+ 2022-12-22 version 2.3.1
2
+
3
+ * Don't treat as error when worker shuts down with exit status 0
4
+
1
5
  2022-06-13 version 2.3.0
2
6
 
3
7
  * Add restart_worker_interval option to prevent workers restart immediately
@@ -13,6 +17,7 @@
13
17
  2022-01-13 version 2.2.5:
14
18
 
15
19
  * Fix DLL load error on Ruby 3.1 on Windows
20
+ * Treat as error when worker shuts down unexpectedly
16
21
 
17
22
  2021-05-24 version 2.2.4:
18
23
 
@@ -147,7 +147,11 @@ module ServerEngine
147
147
  if @stop
148
148
  @worker.logger.info "Worker #{@wid} finished with #{ServerEngine.format_join_status(stat)}"
149
149
  else
150
- @worker.logger.error "Worker #{@wid} finished unexpectedly with #{ServerEngine.format_join_status(stat)}"
150
+ if stat.is_a?(Process::Status) && stat.success?
151
+ @worker.logger.info "Worker #{@wid} exited with #{ServerEngine.format_join_status(stat)}"
152
+ else
153
+ @worker.logger.error "Worker #{@wid} exited unexpectedly with #{ServerEngine.format_join_status(stat)}"
154
+ end
151
155
  end
152
156
  if stat.is_a?(Process::Status) && stat.exited? && @unrecoverable_exit_codes.include?(stat.exitstatus)
153
157
  @unrecoverable_exit = true
@@ -1,3 +1,3 @@
1
1
  module ServerEngine
2
- VERSION = "2.3.0"
2
+ VERSION = "2.3.1"
3
3
  end
data/serverengine.gemspec CHANGED
@@ -28,4 +28,5 @@ Gem::Specification.new do |gem|
28
28
  gem.add_development_dependency 'rake-compiler', ['~> 0.9.4']
29
29
 
30
30
  gem.add_development_dependency "timecop", ["~> 0.9.5"]
31
+ gem.add_development_dependency "rr", ["~> 3.1"]
31
32
  end
data/spec/daemon_spec.rb CHANGED
@@ -2,6 +2,14 @@
2
2
  describe ServerEngine::Daemon do
3
3
  include_context 'test server and worker'
4
4
 
5
+ before do
6
+ @log_path = "tmp/multi-worker-test-#{SecureRandom.hex(10)}.log"
7
+ end
8
+
9
+ after do
10
+ FileUtils.rm_rf(@log_path)
11
+ end
12
+
5
13
  it 'run and graceful stop by signal' do
6
14
  pending "not supported signal base commands on Windows" if ServerEngine.windows?
7
15
 
@@ -111,6 +119,7 @@ describe ServerEngine::Daemon do
111
119
  daemonize: false,
112
120
  supervisor: false,
113
121
  pid_path: "tmp/pid",
122
+ logger: ServerEngine::DaemonLogger.new(@log_path),
114
123
  log_stdout: false,
115
124
  log_stderr: false,
116
125
  unrecoverable_exit_codes: [3,4,5],
@@ -135,6 +144,7 @@ describe ServerEngine::Daemon do
135
144
  supervisor: false,
136
145
  worker_type: 'process',
137
146
  pid_path: "tmp/pid",
147
+ logger: ServerEngine::DaemonLogger.new(@log_path),
138
148
  log_stdout: false,
139
149
  log_stderr: false,
140
150
  unrecoverable_exit_codes: [3,4,5],
@@ -158,6 +168,7 @@ describe ServerEngine::Daemon do
158
168
  supervisor: true,
159
169
  worker_type: 'process',
160
170
  pid_path: "tmp/pid",
171
+ logger: ServerEngine::DaemonLogger.new(@log_path),
161
172
  log_stdout: false,
162
173
  log_stderr: false,
163
174
  unrecoverable_exit_codes: [3,4,5],
@@ -1,13 +1,30 @@
1
+ require 'timeout'
2
+ require 'securerandom'
3
+
1
4
  [ServerEngine::MultiThreadServer, ServerEngine::MultiProcessServer].each do |impl_class|
2
5
  # MultiProcessServer uses fork(2) internally, then it doesn't support Windows.
3
6
 
4
7
  describe impl_class do
5
8
  include_context 'test server and worker'
6
9
 
10
+ before do
11
+ @log_path = "tmp/multi-worker-test-#{SecureRandom.hex(10)}.log"
12
+ @logger = ServerEngine::DaemonLogger.new(@log_path)
13
+ end
14
+
15
+ after do
16
+ FileUtils.rm_rf(@log_path)
17
+ end
18
+
7
19
  it 'scale up' do
8
20
  pending "Windows environment does not support fork" if ServerEngine.windows? && impl_class == ServerEngine::MultiProcessServer
9
21
 
10
- config = {workers: 2, log_stdout: false, log_stderr: false}
22
+ config = {
23
+ workers: 2,
24
+ logger: @logger,
25
+ log_stdout: false,
26
+ log_stderr: false,
27
+ }
11
28
 
12
29
  s = impl_class.new(TestWorker) { config.dup }
13
30
  t = Thread.new { s.main }
@@ -35,7 +52,12 @@
35
52
  it 'scale down' do
36
53
  pending "Windows environment does not support fork" if ServerEngine.windows? && impl_class == ServerEngine::MultiProcessServer
37
54
 
38
- config = {workers: 2, log_stdout: false, log_stderr: false}
55
+ config = {
56
+ workers: 2,
57
+ logger: @logger,
58
+ log_stdout: false,
59
+ log_stderr: false
60
+ }
39
61
 
40
62
  s = impl_class.new(TestWorker) { config.dup }
41
63
  t = Thread.new { s.main }
@@ -59,12 +81,32 @@
59
81
 
60
82
  test_state(:worker_stop).should == 3
61
83
  end
84
+ end
85
+ end
86
+
87
+ [ServerEngine::MultiProcessServer].each do |impl_class|
88
+ describe impl_class do
89
+ include_context 'test server and worker'
90
+
91
+ before do
92
+ @log_path = "tmp/multi-worker-test-#{SecureRandom.hex(10)}.log"
93
+ @logger = ServerEngine::DaemonLogger.new(@log_path)
94
+ end
95
+
96
+ after do
97
+ FileUtils.rm_rf(@log_path)
98
+ end
62
99
 
63
100
  it 'raises SystemExit when all workers exit with specified code by unrecoverable_exit_codes' do
64
- pending "unrecoverable_exit_codes supported only for multi process workers" if impl_class == ServerEngine::MultiThreadServer
65
101
  pending "Windows environment does not support fork" if ServerEngine.windows? && impl_class == ServerEngine::MultiProcessServer
66
102
 
67
- config = {workers: 4, log_stdout: false, log_stderr: false, unrecoverable_exit_codes: [3, 4, 5]}
103
+ config = {
104
+ workers: 4,
105
+ logger: @logger,
106
+ log_stdout: false,
107
+ log_stderr: false,
108
+ unrecoverable_exit_codes: [3, 4, 5]
109
+ }
68
110
 
69
111
  s = impl_class.new(TestExitWorker) { config.dup }
70
112
  raised_error = nil
@@ -85,10 +127,16 @@
85
127
  end
86
128
 
87
129
  it 'raises SystemExit immediately when a worker exits if stop_immediately_at_unrecoverable_exit specified' do
88
- pending "unrecoverable_exit_codes supported only for multi process workers" if impl_class == ServerEngine::MultiThreadServer
89
130
  pending "Windows environment does not support fork" if ServerEngine.windows? && impl_class == ServerEngine::MultiProcessServer
90
131
 
91
- config = {workers: 4, log_stdout: false, log_stderr: false, unrecoverable_exit_codes: [3, 4, 5], stop_immediately_at_unrecoverable_exit: true}
132
+ config = {
133
+ workers: 4,
134
+ logger: @logger,
135
+ log_stdout: false,
136
+ log_stderr: false,
137
+ unrecoverable_exit_codes: [3, 4, 5],
138
+ stop_immediately_at_unrecoverable_exit: true
139
+ }
92
140
 
93
141
  s = impl_class.new(TestExitWorker) { config.dup }
94
142
  raised_error = nil
@@ -111,3 +159,101 @@
111
159
  end
112
160
  end
113
161
  end
162
+
163
+ describe "log level for exited proccess" do
164
+ include_context 'test server and worker'
165
+
166
+ before do
167
+ @log_path = "tmp/multi-process-log-level-test-#{SecureRandom.hex(10)}.log"
168
+ end
169
+
170
+ after do
171
+ FileUtils.rm_rf(@log_path)
172
+ end
173
+
174
+ it 'stop' do
175
+ pending "Windows environment does not support fork" if ServerEngine.windows?
176
+
177
+ config = {
178
+ workers: 1,
179
+ logger: ServerEngine::DaemonLogger.new(@log_path),
180
+ log_stdout: false,
181
+ log_stderr: false,
182
+ }
183
+
184
+ s = ServerEngine::MultiProcessServer.new(TestWorker) { config.dup }
185
+ t = Thread.new { s.main }
186
+
187
+ begin
188
+ wait_for_fork
189
+ test_state(:worker_run).should == 1
190
+ ensure
191
+ s.stop(true)
192
+ t.join
193
+ end
194
+
195
+ log_lines = File.read(@log_path).split("\n")
196
+ expect(log_lines[2]).to match(/^I, \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+ #\d+\] INFO -- : Worker 0 finished with status 0$/)
197
+ end
198
+
199
+ it 'non zero exit status' do
200
+ pending "Windows environment does not support fork" if ServerEngine.windows?
201
+
202
+ config = {
203
+ workers: 1,
204
+ logger: ServerEngine::DaemonLogger.new(@log_path),
205
+ log_stdout: false,
206
+ log_stderr: false,
207
+ unrecoverable_exit_codes: [5],
208
+ }
209
+
210
+ s = ServerEngine::MultiProcessServer.new(TestExitWorker) { config.dup }
211
+ raised_error = nil
212
+ Thread.new do
213
+ begin
214
+ s.main
215
+ rescue SystemExit => e
216
+ raised_error = e
217
+ end
218
+ end.join
219
+
220
+ test_state(:worker_stop).to_i.should == 0
221
+ raised_error.status.should == 5
222
+ log_lines = File.read(@log_path).split("\n")
223
+ expect(log_lines[1]).to match(/^E, \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+ #\d+\] ERROR -- : Worker 0 exited unexpectedly with status 5$/)
224
+ end
225
+
226
+ module TestNormalExitWorker
227
+ include TestExitWorker
228
+ def initialize
229
+ super
230
+ @exit_code = 0
231
+ end
232
+ end
233
+
234
+ it 'zero exit status' do
235
+ pending "Windows environment does not support fork" if ServerEngine.windows?
236
+
237
+ config = {
238
+ workers: 1,
239
+ logger: ServerEngine::DaemonLogger.new(@log_path),
240
+ log_stdout: false,
241
+ log_stderr: false,
242
+ }
243
+
244
+ s = ServerEngine::MultiProcessServer.new(TestNormalExitWorker) { config.dup }
245
+ t = Thread.new { s.main }
246
+
247
+ begin
248
+ Timeout.timeout(5) do
249
+ sleep 1 until File.read(@log_path).include?("INFO -- : Worker 0 exited with status 0")
250
+ end
251
+ ensure
252
+ s.stop(true)
253
+ t.join
254
+ end
255
+
256
+ log_lines = File.read(@log_path).split("\n")
257
+ expect(log_lines[1]).to match(/^I, \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+ #\d+\] INFO -- : Worker 0 exited with status 0$/)
258
+ end
259
+ end
@@ -4,10 +4,25 @@ require 'timecop'
4
4
  describe ServerEngine::MultiSpawnServer do
5
5
  include_context 'test server and worker'
6
6
 
7
+ before do
8
+ @log_path = "tmp/multi-worker-test-#{SecureRandom.hex(10)}.log"
9
+ @logger = ServerEngine::DaemonLogger.new(@log_path)
10
+ end
11
+
12
+ after do
13
+ FileUtils.rm_rf(@log_path)
14
+ end
15
+
7
16
  describe 'starts worker processes' do
8
17
  context 'with command_sender=pipe' do
9
18
  it do
10
- config = {workers: 2, command_sender: 'pipe', log_stdout: false, log_stderr: false}
19
+ config = {
20
+ workers: 2,
21
+ command_sender: 'pipe',
22
+ logger: @logger,
23
+ log_stdout: false,
24
+ log_stderr: false
25
+ }
11
26
 
12
27
  s = ServerEngine::MultiSpawnServer.new(TestWorker) { config.dup }
13
28
  t = Thread.new { s.main }
@@ -32,6 +47,7 @@ describe ServerEngine::MultiSpawnServer do
32
47
  {
33
48
  workers: workers,
34
49
  command_sender: 'pipe',
50
+ logger: @logger,
35
51
  log_stdout: false,
36
52
  log_stderr: false,
37
53
  start_worker_delay: start_worker_delay,
@@ -1,8 +1,12 @@
1
+ require 'rr'
1
2
 
2
3
  describe ServerEngine::Supervisor do
3
4
  include_context 'test server and worker'
4
5
 
5
6
  def start_supervisor(worker = nil, **config)
7
+ config[:log] ||= @log_path
8
+ config[:log_stdout] ||= false
9
+ config[:log_stderr] ||= false
6
10
  if ServerEngine.windows?
7
11
  config[:windows_daemon_cmdline] = windows_supervisor_cmdline(nil, worker, config)
8
12
  end
@@ -13,6 +17,8 @@ describe ServerEngine::Supervisor do
13
17
  end
14
18
 
15
19
  def start_daemon(**config)
20
+ config[:log_stdout] ||= false
21
+ config[:log_stderr] ||= false
16
22
  if ServerEngine.windows?
17
23
  config[:windows_daemon_cmdline] = windows_daemon_cmdline
18
24
  end
@@ -22,9 +28,17 @@ describe ServerEngine::Supervisor do
22
28
  return daemon, t
23
29
  end
24
30
 
31
+ before do
32
+ @log_path = "tmp/supervisor-test-#{SecureRandom.hex(10)}.log"
33
+ end
34
+
35
+ after do
36
+ FileUtils.rm_rf(@log_path)
37
+ end
38
+
25
39
  context 'when :log=IO option is given' do
26
40
  it 'can start' do
27
- daemon, t = start_daemon(log: STDOUT)
41
+ daemon, t = start_daemon(log: File.open(@log_path, "wb"))
28
42
 
29
43
  begin
30
44
  wait_for_fork
@@ -40,7 +54,7 @@ describe ServerEngine::Supervisor do
40
54
 
41
55
  context 'when :logger option is given' do
42
56
  it 'uses specified logger instance' do
43
- logger = ServerEngine::DaemonLogger.new(STDOUT)
57
+ logger = ServerEngine::DaemonLogger.new(@log_path)
44
58
  daemon, t = start_daemon(logger: logger)
45
59
 
46
60
  begin
@@ -57,7 +71,7 @@ describe ServerEngine::Supervisor do
57
71
 
58
72
  context 'when both :logger and :log options are given' do
59
73
  it 'start ignoring :log' do
60
- logger = ServerEngine::DaemonLogger.new(STDOUT)
74
+ logger = ServerEngine::DaemonLogger.new(@log_path)
61
75
  daemon, t = start_daemon(logger: logger, log: STDERR)
62
76
 
63
77
  begin
@@ -188,6 +202,8 @@ describe ServerEngine::Supervisor do
188
202
  it 'auto restart in limited ratio' do
189
203
  pending 'not supported on Windows' if ServerEngine.windows? && sender == 'signal'
190
204
 
205
+ RR.stub(ServerEngine).dump_uncaught_error
206
+
191
207
  sv, t = start_supervisor(RunErrorWorker, server_restart_wait: 1, command_sender: sender)
192
208
 
193
209
  begin
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serverengine
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-13 00:00:00.000000000 Z
11
+ date: 2022-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sigdump
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.9.5
97
+ - !ruby/object:Gem::Dependency
98
+ name: rr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.1'
97
111
  description: A framework to implement robust multiprocess servers like Unicorn
98
112
  email:
99
113
  - frsyuki@gmail.com