navy 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  preload do |admiral|
2
+ # require 'rainbow'
2
3
  admiral.logger.warn "admiral preload"
3
4
  end
4
5
 
@@ -8,7 +9,7 @@ before_fork do |admiral, captain|
8
9
  end
9
10
 
10
11
  after_fork do |admiral, captain|
11
- admiral.logger.warn "admiral (#{captain.label}) after_fork"
12
+ captain.logger.warn "admiral (#{captain.label}) after_fork"
12
13
  captain.logger.warn "captain=#{captain.label} after_fork"
13
14
  end
14
15
 
@@ -19,41 +20,119 @@ pid "/tmp/navy.pid"
19
20
  # stderr_path "/tmp/navy-err.log"
20
21
  # stdout_path "/tmp/navy-out.log"
21
22
 
23
+ module Jack
24
+ extend self
25
+
26
+ def call(officer)
27
+ trap(:QUIT) { exit }
28
+ trap(:TERM) { exit }
29
+ # raise "HELLO"
30
+ n = 0
31
+ loop do
32
+ puts "#{n} jack called (officer=#{officer.number}) pid: #{officer.officer_pid}"
33
+ # Jack.logger.info "#{n} jack logger (officer=#{officer.number}) pid: #{officer.officer_pid}"
34
+ # Navy.logger.info "START_CTX: #{START_CTX.inspect}"
35
+ # Navy.logger.info "Navy::Admiral::CAPTAINS: #{Navy::Admiral::CAPTAINS.inspect}"
36
+ # Navy.logger.info "Navy::Admiral::OFFICERS: #{Navy::Captain::OFFICERS.inspect}"
37
+ sleep officer.number == 0 ? 0.5 : 1
38
+ n += 1
39
+ end
40
+ end
41
+
42
+ def logger#(name = nil)
43
+ require 'logger'
44
+ # @logger = nil if name
45
+ @logger ||= Logger.new('/tmp/jack.log')
46
+ end
47
+
48
+ def readers
49
+ @readers ||= []
50
+ end
51
+
52
+ def reader=(val)
53
+ (@reader = val).tap do |r|
54
+ readers.push(r)
55
+ end
56
+ end
57
+
58
+ def writer=(val)
59
+ @writer = val
60
+ end
61
+
62
+ def reader
63
+ @reader
64
+ end
65
+
66
+ def writer
67
+ @writer
68
+ end
69
+ end
70
+
22
71
  captain :jack do
23
72
 
24
73
  stderr_path "/tmp/navy-jack-err.log"
25
- stdout_path "/tmp/navy-jack-out.log"
74
+ # stdout_path "/tmp/navy-jack-out.log"
26
75
 
27
76
  preload do |captain|
28
77
  captain.logger.warn "captain=#{captain.label} preload"
78
+ # Jack.mutex.synchronize do
79
+ 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
29
97
  end
30
98
 
31
99
  before_fork do |captain, officer|
32
100
  captain.logger.warn "captain=#{captain.label} before_fork"
33
101
  officer.logger.warn "(#{captain.label}) officer=#{officer.number} before_fork"
102
+ Jack.reader, Jack.writer = IO.pipe
103
+ Jack.reader.sync = true
34
104
  end
35
105
 
36
106
  after_fork do |captain, officer|
107
+ Jack.reader.close # we don't read
108
+ Jack.writer.sync = true
37
109
  captain.logger.warn "captain=#{captain.label} after_fork"
38
110
  officer.logger.warn "(#{captain.label}) officer=#{officer.number} after_fork"
111
+ $stdout.reopen Jack.writer
112
+ $stderr.reopen Jack.writer
113
+ end
114
+
115
+ post_fork do |captain, officer|
116
+ Jack.writer.close
39
117
  end
40
118
 
41
119
  respawn_limit 15, 5
42
120
 
43
- officers 2 do |officer|
44
- trap(:QUIT) { exit }
45
- trap(:TERM) { exit }
46
- # raise "HELLO"
47
- n = 0
48
- loop do
49
- Navy.logger.info "#{n} jack called (officer=#{officer.number}) pid: #{officer.officer_pid}"
50
- # Navy.logger.info "START_CTX: #{START_CTX.inspect}"
51
- # Navy.logger.info "Navy::Admiral::CAPTAINS: #{Navy::Admiral::CAPTAINS.inspect}"
52
- # Navy.logger.info "Navy::Admiral::OFFICERS: #{Navy::Captain::OFFICERS.inspect}"
53
- sleep 1
54
- n += 1
55
- end
56
- end
121
+ officers 4, Jack
122
+ # officers 2 do |officer|
123
+ # trap(:QUIT) { exit }
124
+ # trap(:TERM) { exit }
125
+ # # raise "HELLO"
126
+ # n = 0
127
+ # loop do
128
+ # Navy.logger.info "#{n} jack called (officer=#{officer.number}) pid: #{officer.officer_pid}"
129
+ # # Navy.logger.info "START_CTX: #{START_CTX.inspect}"
130
+ # # Navy.logger.info "Navy::Admiral::CAPTAINS: #{Navy::Admiral::CAPTAINS.inspect}"
131
+ # # Navy.logger.info "Navy::Admiral::OFFICERS: #{Navy::Captain::OFFICERS.inspect}"
132
+ # sleep 1
133
+ # n += 1
134
+ # end
135
+ # end
57
136
 
58
137
  end
59
138
 
@@ -61,6 +140,8 @@ captain :blackbeard do
61
140
 
62
141
  pid "/tmp/navy-blackbeard.pid"
63
142
 
143
+ # stderr_path '/tmp/navy-blackbeard-err.log'
144
+
64
145
  officers 5 do
65
146
  trap(:QUIT) { exit }; trap(:TERM) { exit }; loop { sleep 1 }
66
147
  end
@@ -11,7 +11,7 @@ require 'logger'
11
11
  module Navy
12
12
  extend self
13
13
  def logger
14
- @logger ||= Logger.new($stderr)
14
+ @logger ||= Navy::ScopedLogger.new(Logger.new($stderr))
15
15
  end
16
16
 
17
17
  def log_error(logger, prefix, exc)
@@ -21,6 +21,7 @@ module Navy
21
21
  exc.backtrace.each { |line| logger.error(line) }
22
22
  end
23
23
  end
24
+ require 'navy/scoped_logger'
24
25
  require 'navy/util'
25
26
  require 'navy/orders'
26
27
  require 'navy/rank'
@@ -30,6 +30,8 @@ class Navy::Admiral < Navy::Rank
30
30
  attr_reader :options
31
31
 
32
32
  def initialize(options = {})
33
+ self.orig_stderr = $stderr.dup
34
+ self.orig_stdout = $stdout.dup
33
35
  self.reexec_pid = 0
34
36
 
35
37
  @options = options.dup
@@ -243,7 +245,10 @@ class Navy::Admiral < Navy::Rank
243
245
  CAPTAINS[pid] = captain
244
246
  RESPAWNS[label] ||= []
245
247
  RESPAWNS[label].push(Time.now)
248
+ captain.captain_pid = pid
249
+ post_fork.call(self, captain) if post_fork
246
250
  else
251
+ captain.orders.give!(captain, only: [ :stderr_path, :stdout_path ])
247
252
  after_fork.call(self, captain) if after_fork
248
253
  captain.start.join
249
254
  exit
@@ -11,6 +11,9 @@ class Navy::Admiral::Orders < Navy::Orders
11
11
  admiral.logger.info("forked child re-executing...")
12
12
  end,
13
13
  captains: {},
14
+ post_fork: ->(admiral, captain) do
15
+ admiral.logger.debug("captain=#{captain.label} post-fork") if $DEBUG
16
+ end,
14
17
  preload: ->(admiral) do
15
18
  admiral.logger.info("admiral preloading...")
16
19
  end,
@@ -16,6 +16,9 @@ class Navy::Captain < Navy::Rank
16
16
  attr_reader :admiral, :options
17
17
 
18
18
  def initialize(admiral, label, config, options = {})
19
+ self.orig_stderr = $stderr.dup
20
+ self.orig_stdout = $stdout.dup
21
+
19
22
  @options = options.dup
20
23
  @options[:use_defaults] = true
21
24
  @options[:config_file] = config
@@ -32,11 +35,12 @@ class Navy::Captain < Navy::Rank
32
35
  end
33
36
 
34
37
  def start
35
- orders.give!(self, only: [ :stderr_path, :stdout_path ])
36
38
  init_self_pipe!
37
39
  QUEUE_SIGS.each do |sig|
38
40
  trap(sig) do
39
- logger.debug "captain[#{label}] received #{sig}" if $DEBUG
41
+ if $DEBUG
42
+ logger.debug "captain[#{label}] received #{sig}"
43
+ end
40
44
  SIG_QUEUE << sig
41
45
  awaken_captain
42
46
  end
@@ -187,6 +191,8 @@ class Navy::Captain < Navy::Rank
187
191
  OFFICERS[pid] = officer
188
192
  RESPAWNS[n] ||= []
189
193
  RESPAWNS[n].push(Time.now)
194
+ officer.officer_pid = pid
195
+ post_fork.call(self, officer) if post_fork
190
196
  else
191
197
  after_fork.call(self, officer) if after_fork
192
198
  officer.start
@@ -9,6 +9,9 @@ class Navy::Captain::Orders < Navy::Orders
9
9
  end,
10
10
  officer_job: -> { trap(:QUIT) { exit }; trap(:TERM) { exit }; loop { sleep 1 } },
11
11
  officer_count: 0,
12
+ post_fork: ->(captain, officer) do
13
+ captain.logger.debug("(#{captain.label}) officer=#{officer.number} post-fork") if $DEBUG
14
+ end,
12
15
  preload: ->(captain) do
13
16
  captain.logger.info("captain=#{captain.label} preloading...")
14
17
  end,
@@ -2,11 +2,14 @@ class Navy::Rank
2
2
 
3
3
  attr_accessor :orders
4
4
 
5
- attr_accessor :before_fork, :after_fork, :before_exec
6
- attr_accessor :reexec_pid
5
+ attr_accessor :before_fork, :after_fork, :before_exec, :post_fork
6
+ attr_reader :stdout_path, :stderr_path
7
+ attr_accessor :reexec_pid, :orig_stdout, :orig_stderr, :current_stdout, :current_stderr
7
8
 
8
9
  def logger
9
- @logger ||= orders[:logger]
10
+ (@logger ||= orders[:logger]).tap do |log|
11
+ log.scope = self #if log.respond_to?(:scope=)
12
+ end
10
13
  end
11
14
  attr_writer :logger
12
15
 
@@ -45,8 +48,14 @@ class Navy::Rank
45
48
 
46
49
  attr_accessor :preload
47
50
 
48
- def stdout_path=(path); redirect_io($stdout, path); end
49
- def stderr_path=(path); redirect_io($stderr, path); end
51
+ def stdout_path=(path)
52
+ @stdout_path = path
53
+ redirect_io($stdout, path)
54
+ end
55
+ def stderr_path=(path)
56
+ @stderr_path = path
57
+ redirect_io($stderr, path)
58
+ end
50
59
 
51
60
  attr_accessor :timeout
52
61
 
@@ -0,0 +1,74 @@
1
+ class Navy::ScopedLogger
2
+
3
+ attr_accessor :logger, :scope
4
+
5
+ def initialize(logger, scope = nil)
6
+ @logger, @scope = logger, scope
7
+ end
8
+
9
+ def add(*args, &block)
10
+ scoped(:add, *args, &block)
11
+ end
12
+
13
+ def debug(*args, &block)
14
+ scoped(:debug, *args, &block)
15
+ end
16
+
17
+ def info(*args, &block)
18
+ scoped(:info, *args, &block)
19
+ end
20
+
21
+ def warn(*args, &block)
22
+ scoped(:warn, *args, &block)
23
+ end
24
+
25
+ def error(*args, &block)
26
+ scoped(:error, *args, &block)
27
+ end
28
+
29
+ def fatal(*args, &block)
30
+ scoped(:fatal, *args, &block)
31
+ end
32
+
33
+ def respond_to?(*args)
34
+ @logger.respond_to?(*args)
35
+ end
36
+
37
+ protected
38
+
39
+ def method_missing(name, *args, &block)
40
+ @logger.__send__(name, *args, &block)
41
+ end
42
+
43
+ def scoped(name, *args, &block)
44
+ start_scope!
45
+ retval = @logger.__send__(name, *args, &block)
46
+ stop_scope!
47
+ return retval
48
+ end
49
+
50
+ def start_scope!
51
+ return unless scope
52
+ scope.current_stdout = $stdout.dup
53
+ scope.current_stderr = $stderr.dup
54
+ if scope.stderr_path
55
+ scope.stderr_path = scope.stderr_path
56
+ else
57
+ $stderr.reopen scope.orig_stderr
58
+ end
59
+ if scope.stdout_path
60
+ scope.stdout_path = scope.stdout_path
61
+ else
62
+ $stdout.reopen scope.orig_stdout
63
+ end
64
+ end
65
+
66
+ def stop_scope!
67
+ return unless scope
68
+ return unless scope.current_stderr and scope.current_stdout
69
+ $stdout.reopen scope.current_stdout
70
+ $stderr.reopen scope.current_stderr
71
+ scope.current_stderr = scope.current_stdout = nil
72
+ end
73
+
74
+ end
@@ -33,6 +33,10 @@ class Navy::Speak
33
33
 
34
34
  def pid(path); set_path(:pid, path); end
35
35
 
36
+ def post_fork(*args, &block)
37
+ set_hook(:post_fork, block_given? ? block : args[0])
38
+ end
39
+
36
40
  def preload(*args, &block)
37
41
  set_hook(:preload, block_given? ? block : args[0], 1)
38
42
  end
@@ -1,3 +1,3 @@
1
1
  module Navy
2
- VERSION = "1.0.5"
2
+ VERSION = "1.0.6"
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.5
4
+ version: 1.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-05 00:00:00.000000000 Z
12
+ date: 2012-03-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pry
16
- requirement: &70170585246280 !ruby/object:Gem::Requirement
16
+ requirement: &70207025737040 !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: *70170585246280
24
+ version_requirements: *70207025737040
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70170585245840 !ruby/object:Gem::Requirement
27
+ requirement: &70207025736560 !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: *70170585245840
35
+ version_requirements: *70207025736560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70170585245300 !ruby/object:Gem::Requirement
38
+ requirement: &70207025735780 !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: *70170585245300
46
+ version_requirements: *70207025735780
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: kgio
49
- requirement: &70170585244760 !ruby/object:Gem::Requirement
49
+ requirement: &70207025735040 !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: *70170585244760
57
+ version_requirements: *70207025735040
58
58
  description: Ruby daemon inspired by Unicorn.
59
59
  email:
60
60
  - potatosaladx@gmail.com
@@ -80,6 +80,7 @@ files:
80
80
  - lib/navy/officer.rb
81
81
  - lib/navy/orders.rb
82
82
  - lib/navy/rank.rb
83
+ - lib/navy/scoped_logger.rb
83
84
  - lib/navy/ship.rb
84
85
  - lib/navy/speak.rb
85
86
  - lib/navy/util.rb