navy 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,12 +20,52 @@ pid "/tmp/navy.pid"
20
20
  # stderr_path "/tmp/navy-err.log"
21
21
  # stdout_path "/tmp/navy-out.log"
22
22
 
23
+ # class Jacky
24
+
25
+ # SELF_PIPE = []
26
+
27
+ # def initialize
28
+ # init_self_pipe!
29
+ # end
30
+
31
+ # def call(officer)
32
+ # trap(:QUIT) { exit }
33
+ # trap(:TERM) { exit }
34
+ # # raise "HELLO"
35
+ # n = 0
36
+ # loop do
37
+ # puts "#{n} jack called (officer=#{officer.number}) pid: #{officer.officer_pid}"
38
+ # # Jack.logger.info "#{n} jack logger (officer=#{officer.number}) pid: #{officer.officer_pid}"
39
+ # # Navy.logger.info "START_CTX: #{START_CTX.inspect}"
40
+ # # Navy.logger.info "Navy::Admiral::CAPTAINS: #{Navy::Admiral::CAPTAINS.inspect}"
41
+ # # Navy.logger.info "Navy::Admiral::OFFICERS: #{Navy::Captain::OFFICERS.inspect}"
42
+ # sleep officer.number == 0 ? 0.5 : 1
43
+ # n += 1
44
+ # end
45
+ # end
46
+
47
+ # def logger
48
+ # @logger ||= Logger.new('/tmp/jack.log')
49
+ # end
50
+
51
+ # private
52
+
53
+ # def init_self_pipe!
54
+
55
+ # end
56
+
57
+ # end
58
+
23
59
  module Jack
60
+
61
+ SELF_PIPE = []
62
+
24
63
  extend self
25
64
 
26
65
  def call(officer)
27
66
  trap(:QUIT) { exit }
28
67
  trap(:TERM) { exit }
68
+
29
69
  # raise "HELLO"
30
70
  n = 0
31
71
  loop do
@@ -39,20 +79,20 @@ module Jack
39
79
  end
40
80
  end
41
81
 
42
- def logger#(name = nil)
43
- require 'logger'
44
- # @logger = nil if name
82
+ def logger
45
83
  @logger ||= Logger.new('/tmp/jack.log')
46
84
  end
47
85
 
86
+ def logger=(val)
87
+ @logger = val
88
+ end
89
+
48
90
  def readers
49
- @readers ||= []
91
+ @readers ||= {}
50
92
  end
51
93
 
52
94
  def reader=(val)
53
- (@reader = val).tap do |r|
54
- readers.push(r)
55
- end
95
+ @reader = val
56
96
  end
57
97
 
58
98
  def writer=(val)
@@ -66,6 +106,71 @@ module Jack
66
106
  def writer
67
107
  @writer
68
108
  end
109
+
110
+ def main_reader=(val)
111
+ @main_reader = val
112
+ end
113
+
114
+ def main_writer=(val)
115
+ @main_writer = val
116
+ end
117
+
118
+ def main_reader
119
+ @main_reader
120
+ end
121
+
122
+ def main_writer
123
+ @main_writer
124
+ end
125
+
126
+ def threads
127
+ @threads ||= {}
128
+ end
129
+
130
+ def start
131
+ @thread ||= Thread.new do
132
+ loop do
133
+ IO.select([ SELF_PIPE[0] ], nil, nil, 0.1) or next
134
+ data = SELF_PIPE[0].gets
135
+ next unless data
136
+ data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
137
+ pid, message = data.split(',', 2)
138
+ Jack.logger.info "YOUR PID WAS: #{pid}; #{message.strip}"
139
+ # Jack.logger.info data
140
+ end
141
+ end
142
+ end
143
+
144
+ def stop
145
+ if @thread
146
+ @thread.terminate rescue nil
147
+ end
148
+ SELF_PIPE.each { |io| io.close rescue nil }
149
+ end
150
+
151
+ # def main_thread(captain = nil)
152
+ # @main_thread = nil if @main_thread and @main_thread.stop?
153
+ # if @main_thread.nil?
154
+ # # Jack.main_reader.close rescue nil
155
+ # # Jack.main_writer.close rescue nil
156
+ # Jack.main_reader, Jack.main_writer = IO.pipe
157
+ # Jack.main_reader.sync = true
158
+ # Jack.main_writer.sync = true
159
+ # end
160
+ # @main_thread ||= Thread.new do
161
+ # readers = [Jack.main_reader]
162
+ # loop do
163
+ # rs, ws = IO.select(readers, [], [], 1)
164
+ # (rs || []).each do |r|
165
+ # data = r.gets
166
+ # next unless data
167
+ # data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
168
+ # ps, message = data.split(",", 2)
169
+ # Jack.logger.info "pid: #{ps}, message: #{message.to_s.strip}"
170
+ # end
171
+ # end
172
+ # end
173
+ # end
69
174
  end
70
175
 
71
176
  captain :jack do
@@ -75,45 +180,100 @@ captain :jack do
75
180
 
76
181
  preload do |captain|
77
182
  captain.logger.warn "captain=#{captain.label} preload"
78
- # Jack.mutex.synchronize do
183
+ Jack::SELF_PIPE.each { |io| io.close rescue nil }
184
+ # Jack::SELF_PIPE.replace(Kgio::Pipe.new)
185
+ Jack::SELF_PIPE.replace(IO.pipe)
186
+ Jack::SELF_PIPE.each { |io| io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC); io.sync = true }
79
187
  Jack.logger.info "preload"
80
- # end
81
- Thread.new do
82
- loop do
83
- rs, ws = IO.select(Jack.readers, [], [], 1)
84
- (rs || []).each do |r|
85
- data = r.gets
86
- next unless data
87
- data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
88
- # ps, message = data.split(",", 2)
89
- # color = colors[ps.split(".").first]
90
- # info message, ps, color
91
- # Jack.mutex.synchronize do
92
- Jack.logger.info data.strip
93
- # end
94
- end
95
- end
96
- end
188
+ Jack.start
97
189
  end
98
190
 
99
191
  before_fork do |captain, officer|
192
+ # Jack.main_thread(captain)
100
193
  captain.logger.warn "captain=#{captain.label} before_fork"
101
194
  officer.logger.warn "(#{captain.label}) officer=#{officer.number} before_fork"
102
- Jack.reader, Jack.writer = IO.pipe
103
- Jack.reader.sync = true
195
+ # if r = Jack.readers.delete(officer.number)
196
+ # r.close
197
+ # end
198
+ # Jack.readers[officer.number], Jack.writer = IO.pipe
199
+ # Jack.reader = Jack.readers[officer.number]
200
+ # Jack.reader.sync = true
104
201
  end
105
202
 
106
203
  after_fork do |captain, officer|
107
- Jack.reader.close # we don't read
108
- Jack.writer.sync = true
204
+ # Jack.reader.close # we don't read
205
+ # Jack.writer.sync = true
109
206
  captain.logger.warn "captain=#{captain.label} after_fork"
110
207
  officer.logger.warn "(#{captain.label}) officer=#{officer.number} after_fork"
111
- $stdout.reopen Jack.writer
112
- $stderr.reopen Jack.writer
208
+ # $stdout.reopen Jack.writer
209
+ # $stderr.reopen Jack.writer
210
+
211
+ reader, writer = IO.pipe
212
+ $stdout.reopen writer
213
+ $stdout.reopen writer
214
+
215
+ Thread.new do
216
+ until reader.eof?
217
+ Jack::SELF_PIPE[1].puts "%s,%s" % [ officer.officer_pid, reader.gets ]
218
+ end
219
+ end
220
+ end
221
+
222
+ after_stop do |captain, graceful|
223
+ Jack.stop if graceful
113
224
  end
114
225
 
115
226
  post_fork do |captain, officer|
116
- Jack.writer.close
227
+ # Jack.writer.close # we don't write
228
+ # if t = Jack.threads[officer.number]
229
+ # t.terminate unless t.stop?
230
+ # else
231
+ # Jack.threads[officer.number] = Thread.new do
232
+ # reader = Jack.reader
233
+ # until reader.eof?
234
+ # Jack::SELF_PIPE[1].puts "%s,%s" % [ officer.officer_pid, reader.gets ]
235
+ # end
236
+ # end
237
+ # end
238
+ # Jack.reader.lcose
239
+ # Thread.new do
240
+ # # Jack.main_reader.close
241
+ # # Jack.main_writer.close
242
+ # loop do
243
+ # rs, ws = IO.select([Jack.reader], [], [], 1)
244
+ # (rs || []).each do |r|
245
+ # data = r.gets
246
+ # next unless data
247
+ # data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
248
+ # # ps, message = data.split(",", 2)
249
+ # # color = colors[ps.split(".").first]
250
+ # # info message, ps, color
251
+ # # Jack.mutex.synchronize do
252
+ # # Jack.logger.info "pid: #{ps}, message: #{message}"
253
+ # # Jack.logger.info data.strip
254
+ # # end
255
+ # Jack.main_writer.puts "pidpidpid: #{officer.officer_pid}, message: #{data}"
256
+ # end
257
+ # end
258
+ # end
259
+ # Thread.new do
260
+ # reader, writer = Jack.reader, Jack.writer
261
+ # loop do
262
+ # rs, ws = IO.select([reader], [], [], 1)
263
+ # (rs || []).each do |r|
264
+ # data = r.gets
265
+ # next unless data
266
+ # data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
267
+ # # ps, message = data.split(",", 2)
268
+ # # color = colors[ps.split(".").first]
269
+ # # info message, ps, color
270
+ # # Jack.mutex.synchronize do
271
+ # # Jack.logger.info "pid: #{ps}, message: #{message}"
272
+ # writer.write "%s,%s" [ '13', data ]
273
+ # # end
274
+ # end
275
+ # end
276
+ # end
117
277
  end
118
278
 
119
279
  respawn_limit 15, 5
@@ -131,6 +131,7 @@ class Navy::Admiral < Navy::Rank
131
131
 
132
132
  # Terminates all captains, but does not exit admiral process
133
133
  def stop(graceful = true)
134
+ before_stop.call(self, graceful) if before_stop
134
135
  limit = Time.now + timeout
135
136
  until CAPTAINS.empty? || Time.now > limit
136
137
  kill_each_captain(graceful ? :QUIT : :TERM)
@@ -138,6 +139,7 @@ class Navy::Admiral < Navy::Rank
138
139
  reap_all_captains
139
140
  end
140
141
  kill_each_captain(:KILL)
142
+ after_stop.call(self, graceful) if after_stop
141
143
  end
142
144
 
143
145
  private
@@ -4,12 +4,18 @@ class Navy::Admiral::Orders < Navy::Orders
4
4
  after_fork: ->(admiral, captain) do
5
5
  admiral.logger.info("captain=#{captain.label} spawned pid=#{$$}")
6
6
  end,
7
+ after_stop: ->(admiral, graceful) do
8
+ admiral.logger.debug("admiral after (#{graceful ? 'graceful' : 'hard'}) stop") if $DEBUG
9
+ end,
7
10
  before_fork: ->(admiral, captain) do
8
11
  admiral.logger.info("captain=#{captain.label} spawning...")
9
12
  end,
10
13
  before_exec: ->(admiral) do
11
14
  admiral.logger.info("forked child re-executing...")
12
15
  end,
16
+ before_stop: ->(admiral, graceful) do
17
+ admiral.logger.debug("admiral before (#{graceful ? 'graceful' : 'hard'}) stop") if $DEBUG
18
+ end,
13
19
  captains: {},
14
20
  post_fork: ->(admiral, captain) do
15
21
  admiral.logger.debug("captain=#{captain.label} post-fork") if $DEBUG
@@ -120,6 +120,7 @@ class Navy::Captain < Navy::Rank
120
120
 
121
121
  # Terminates all captains, but does not exit admiral process
122
122
  def stop(graceful = true)
123
+ before_stop.call(self, graceful) if before_stop
123
124
  limit = Time.now + timeout
124
125
  until OFFICERS.empty? || Time.now > limit
125
126
  kill_each_officer(graceful ? :QUIT : :TERM)
@@ -127,6 +128,7 @@ class Navy::Captain < Navy::Rank
127
128
  reap_all_officers
128
129
  end
129
130
  kill_each_officer(:KILL)
131
+ after_stop.call(self, graceful) if after_stop
130
132
  end
131
133
 
132
134
  private
@@ -4,9 +4,15 @@ class Navy::Captain::Orders < Navy::Orders
4
4
  after_fork: ->(captain, officer) do
5
5
  captain.logger.info("(#{captain.label}) officer=#{officer.number} spawned pid=#{$$}")
6
6
  end,
7
+ after_stop: ->(captain, graceful) do
8
+ captain.logger.debug("captain=#{captain.label} after (#{graceful ? 'graceful' : 'hard'}) stop") if $DEBUG
9
+ end,
7
10
  before_fork: ->(captain, officer) do
8
11
  captain.logger.info("(#{captain.label}) officer=#{officer.number} spawning...")
9
12
  end,
13
+ before_stop: ->(captain, graceful) do
14
+ captain.logger.debug("captain=#{captain.label} before (#{graceful ? 'graceful' : 'hard'}) stop") if $DEBUG
15
+ end,
10
16
  officer_job: -> { trap(:QUIT) { exit }; trap(:TERM) { exit }; loop { sleep 1 } },
11
17
  officer_count: 0,
12
18
  post_fork: ->(captain, officer) do
@@ -2,7 +2,7 @@ class Navy::Rank
2
2
 
3
3
  attr_accessor :orders
4
4
 
5
- attr_accessor :before_fork, :after_fork, :before_exec, :post_fork
5
+ attr_accessor :before_fork, :after_fork, :before_exec, :post_fork, :before_stop, :after_stop
6
6
  attr_reader :stdout_path, :stderr_path
7
7
  attr_accessor :reexec_pid, :orig_stdout, :orig_stderr, :current_stdout, :current_stderr
8
8
 
@@ -18,10 +18,18 @@ class Navy::Speak
18
18
  set_hook(:after_fork, block_given? ? block : args[0])
19
19
  end
20
20
 
21
+ def after_stop(*args, &block)
22
+ set_hook(:after_stop, block_given? ? block : args[0])
23
+ end
24
+
21
25
  def before_fork(*args, &block)
22
26
  set_hook(:before_fork, block_given? ? block : args[0])
23
27
  end
24
28
 
29
+ def before_stop(*args, &block)
30
+ set_hook(:before_stop, block_given? ? block : args[0])
31
+ end
32
+
25
33
  def logger(obj)
26
34
  %w(debug info warn error fatal).each do |m|
27
35
  obj.respond_to?(m) and next
@@ -1,3 +1,3 @@
1
1
  module Navy
2
- VERSION = "1.0.6"
2
+ VERSION = "1.0.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: navy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-03-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pry
16
- requirement: &70207025737040 !ruby/object:Gem::Requirement
16
+ requirement: &70187979402440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70207025737040
24
+ version_requirements: *70187979402440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70207025736560 !ruby/object:Gem::Requirement
27
+ requirement: &70187979401840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70207025736560
35
+ version_requirements: *70187979401840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70207025735780 !ruby/object:Gem::Requirement
38
+ requirement: &70187979401100 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.8.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70207025735780
46
+ version_requirements: *70187979401100
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: kgio
49
- requirement: &70207025735040 !ruby/object:Gem::Requirement
49
+ requirement: &70187979400340 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '2.6'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70207025735040
57
+ version_requirements: *70187979400340
58
58
  description: Ruby daemon inspired by Unicorn.
59
59
  email:
60
60
  - potatosaladx@gmail.com