sponges 0.5.0.1.pre → 0.5.0.2.pre

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