sponges 0.5.0.1.pre → 0.5.0.2.pre

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sponges.rb CHANGED
@@ -3,7 +3,9 @@ require 'boson/runner'
3
3
  require 'socket'
4
4
  require 'logger'
5
5
  require 'machine'
6
+ require 'forwardable'
6
7
  require_relative 'sponges/configuration'
8
+ require_relative 'sponges/handler'
7
9
  require_relative 'sponges/supervisor'
8
10
  require_relative 'sponges/runner'
9
11
  require_relative 'sponges/commander'
@@ -13,7 +15,8 @@ require_relative 'sponges/store/memory'
13
15
  require_relative 'sponges/store/redis'
14
16
 
15
17
  module Sponges
16
- SIGNALS = [:INT, :QUIT, :TERM]
18
+ STOP_SIGNALS = [:INT, :QUIT, :TERM]
19
+ SIGNALS = STOP_SIGNALS + [:HUP, :TTIN, :TTOU, :CHLD]
17
20
 
18
21
  def configure(&block)
19
22
  Sponges::Configuration.configure &block
@@ -106,7 +106,7 @@ module Sponges
106
106
  end
107
107
 
108
108
  def alive?(pid)
109
- !!Sys::ProcTable.ps.find {|f| f.pid == pid }.nil?
109
+ !Sys::ProcTable.ps.find {|f| f.pid == pid }.nil?
110
110
  end
111
111
 
112
112
  def gracefully?
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+ module Sponges
3
+ class Handler
4
+ extend Forwardable
5
+ attr_reader :supervisor
6
+
7
+ def initialize(supervisor)
8
+ @supervisor = supervisor
9
+ at_exit do
10
+ for_supervisor do
11
+ Sponges.logger.info "Supervisor exits."
12
+ end
13
+ end
14
+ end
15
+
16
+ def call(signal)
17
+ if Sponges::SIGNALS.include?(signal = find_signal(signal))
18
+ send "handler_#{signal.to_s.downcase}", signal
19
+ end
20
+ end
21
+
22
+ def_delegators :@supervisor, :store, :fork_children, :name, :children_name
23
+
24
+ private
25
+
26
+ def for_supervisor
27
+ yield if Process.pid == store.supervisor_pid
28
+ end
29
+
30
+ def find_signal(signal)
31
+ return signal if signal.is_a?(Symbol)
32
+ if signal = Signal.list.find {|k,v| v == signal }
33
+ signal.first.to_sym
34
+ end
35
+ end
36
+
37
+ def handler_ttin(signal)
38
+ for_supervisor do
39
+ Sponges.logger.warn "Supervisor increment child's pool by one."
40
+ fork_children
41
+ end
42
+ end
43
+
44
+ def handler_ttou(signal)
45
+ for_supervisor do
46
+ Sponges.logger.warn "Supervisor decrement child's pool by one."
47
+ if store.children_pids.first
48
+ kill_one(store.children_pids.first, :HUP)
49
+ store.delete_children(store.children_pids.first)
50
+ else
51
+ Sponges.logger.warn "No more child to kill."
52
+ end
53
+ end
54
+ end
55
+
56
+ def handler_chld(signal)
57
+ for_supervisor do
58
+ store.children_pids.each do |pid|
59
+ begin
60
+ if dead = Process.waitpid(pid.to_i, Process::WNOHANG)
61
+ Sponges.logger.warn "Child #{dead} died. Restarting a new one..."
62
+ store.delete_children dead
63
+ Sponges::Hook.on_chld
64
+ fork_children
65
+ end
66
+ rescue Errno::ECHILD => e
67
+ # Don't panic
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def handler_int(signal)
74
+ Sponges.logger.info "Supervisor received #{signal} signal."
75
+ kill_them_all(signal)
76
+ Process.waitall
77
+ Sponges.logger.info "Children shutdown complete."
78
+ Sponges.logger.info "Supervisor shutdown. Exiting..."
79
+ store.clear(name)
80
+ exit
81
+ rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
82
+ # Don't panic
83
+ end
84
+
85
+ alias handler_quit handler_int
86
+ alias handler_term handler_int
87
+
88
+ def kill_them_all(signal)
89
+ store.children_pids.each do |pid|
90
+ kill_one(pid.to_i, signal)
91
+ end
92
+ end
93
+
94
+ def kill_one(pid, signal)
95
+ begin
96
+ Process.kill signal, pid
97
+ Process.waitpid pid
98
+ Sponges.logger.info "Child #{pid} receive a #{signal} signal."
99
+ rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
100
+ # Don't panic
101
+ end
102
+ end
103
+
104
+ def fork_children
105
+ name = children_name
106
+ pid = fork do
107
+ $PROGRAM_NAME = name
108
+ (Sponges::STOP_SIGNALS + [:HUP]).each{ |sig| trap(sig) { exit!(0) } }
109
+ Sponges::Hook.after_fork
110
+ supervisor.call
111
+ end
112
+ Sponges.logger.info "Supervisor create a child with #{pid} pid."
113
+ store.add_children pid
114
+ end
115
+ end
116
+ end
@@ -50,7 +50,6 @@ module Sponges
50
50
 
51
51
  def fork_supervisor
52
52
  fork do
53
- $PROGRAM_NAME = "#{@name}_supervisor"
54
53
  Supervisor.new(@name, @options, store, @block).start
55
54
  end
56
55
  end
@@ -1,6 +1,4 @@
1
1
  # encoding: utf-8
2
- require 'forwardable'
3
-
4
2
  module Sponges
5
3
  class Store
6
4
  class Memory
@@ -1,111 +1,45 @@
1
1
  # encoding: utf-8
2
2
  module Sponges
3
3
  class Supervisor
4
- attr_reader :store, :name, :options
4
+ attr_reader :store, :name, :options, :handler
5
5
 
6
6
  def initialize(name, options, store, block)
7
7
  @name, @options, @store, @block = name, options, store, block
8
+ $PROGRAM_NAME = "#{@name}_supervisor"
8
9
  store.on_fork
9
10
  store.register Process.pid
10
11
  @children_seen = 0
12
+ @handler = Handler.new self
11
13
  end
12
14
 
13
15
  def start
14
16
  trap_signals
15
- at_exit do
16
- Sponges.logger.info "Supervisor exits."
17
- end
18
17
  options[:size].times do
19
- fork_children
18
+ handler.call :TTIN
20
19
  end
21
20
  Sponges.logger.info "Supervisor started, waiting for messages."
22
21
  sleep
23
22
  rescue Exception => exception
24
23
  Sponges.logger.error exception
25
- kill_them_all(:INT)
24
+ handler.call :INT
26
25
  raise exception
27
26
  end
28
27
 
29
- private
30
-
31
- def fork_children
32
- name = children_name
33
- pid = fork do
34
- $PROGRAM_NAME = name
35
- (Sponges::SIGNALS + [:HUP]).each{ |sig| trap(sig) { exit!(0) } }
36
- Sponges::Hook.after_fork
37
- @block.call
38
- end
39
- Sponges.logger.info "Supervisor create a child with #{pid} pid."
40
- store.add_children pid
28
+ def call
29
+ @block.call
41
30
  end
42
31
 
32
+ private
33
+
43
34
  def children_name
44
35
  "#{name}_child_#{@children_seen +=1}"
45
36
  end
46
37
 
47
38
  def trap_signals
48
- (Sponges::SIGNALS + [:HUP]).each do |signal|
49
- trap(signal) do
50
- handle_signal signal
51
- end
52
- end
53
- trap(:TTIN) do
54
- Sponges.logger.warn "Supervisor increment child's pool by one."
55
- fork_children
56
- end
57
- trap(:TTOU) do
58
- Sponges.logger.warn "Supervisor decrement child's pool by one."
59
- if store.children_pids.first
60
- kill_one(store.children_pids.first, :HUP)
61
- store.delete_children(store.children_pids.first)
62
- else
63
- Sponges.logger.warn "No more child to kill."
64
- end
65
- end
66
- trap(:CHLD) do
67
- store.children_pids.each do |pid|
68
- begin
69
- dead = Process.waitpid(pid.to_i, Process::WNOHANG)
70
- if dead
71
- Sponges.logger.warn "Child #{dead} died. Restarting a new one..."
72
- store.delete_children dead
73
- Sponges::Hook.on_chld
74
- fork_children
75
- end
76
- rescue Errno::ECHILD => e
77
- # Don't panic
78
- end
79
- end
80
- end
81
- end
82
-
83
- def handle_signal(signal)
84
- Sponges.logger.info "Supervisor received #{signal} signal."
85
- kill_them_all(signal)
86
- Process.waitall
87
- Sponges.logger.info "Children shutdown complete."
88
- Sponges.logger.info "Supervisor shutdown. Exiting..."
89
- store.clear(name)
90
- exit
91
- rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
92
- # Don't panic
93
- end
94
-
95
- def kill_them_all(signal)
96
- store.children_pids.each do |pid|
97
- kill_one(pid.to_i, signal)
39
+ Sponges::SIGNALS.each do |signal|
40
+ trap(signal) {|signal| handler.call signal }
98
41
  end
99
42
  end
100
43
 
101
- def kill_one(pid, signal)
102
- begin
103
- Process.kill signal, pid
104
- Process.waitpid pid
105
- Sponges.logger.info "Child #{pid} receive a #{signal} signal."
106
- rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
107
- # Don't panic
108
- end
109
- end
110
44
  end
111
45
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Sponges
3
- VERSION = "0.5.0.1.pre"
3
+ VERSION = "0.5.0.2.pre"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sponges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.1.pre
4
+ version: 0.5.0.2.pre
5
5
  prerelease: 8
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-01-28 00:00:00.000000000 Z
12
+ date: 2013-01-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: boson
@@ -75,6 +75,7 @@ files:
75
75
  - lib/sponges/cli.rb
76
76
  - lib/sponges/commander.rb
77
77
  - lib/sponges/configuration.rb
78
+ - lib/sponges/handler.rb
78
79
  - lib/sponges/runner.rb
79
80
  - lib/sponges/store.rb
80
81
  - lib/sponges/store/memory.rb