navy 1.0.5 → 1.0.6

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.
@@ -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