sponges 0.5.0.pre → 0.5.0

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/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # sponges
2
2
 
3
+ [![Code
4
+ Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/AF83/sponges)
5
+ [![Gem
6
+ Version](https://fury-badge.herokuapp.com/rb/sponges.png)](http://badge.fury.io/rb/sponges)
7
+
3
8
  When I build workers, I want them to be like an army of spongebobs, always
4
9
  stressed and eager to work. `sponges` helps you build this army of sponges, to
5
10
  control them, and, well, to kill them gracefully. Making them stressed and eager
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
data/lib/sponges/cli.rb CHANGED
@@ -39,6 +39,7 @@ module Sponges
39
39
  desc "Restart workers"
40
40
  def restart(options = {})
41
41
  stop(options)
42
+ sleep 1
42
43
  start(options)
43
44
  end
44
45
 
@@ -106,12 +106,7 @@ module Sponges
106
106
  end
107
107
 
108
108
  def alive?(pid)
109
- begin
110
- Process.kill 0, pid
111
- true
112
- rescue Errno::ESRCH => e
113
- false
114
- end
109
+ !Sys::ProcTable.ps.find {|f| f.pid == pid }.nil?
115
110
  end
116
111
 
117
112
  def gracefully?
@@ -0,0 +1,126 @@
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
+ return if stopping?
59
+ store.children_pids.each do |pid|
60
+ begin
61
+ if dead = Process.waitpid(pid.to_i, Process::WNOHANG)
62
+ store.delete_children dead
63
+ Sponges.logger.warn "Child #{dead} died. Restarting a new one..."
64
+ Sponges::Hook.on_chld
65
+ fork_children
66
+ end
67
+ rescue Errno::ECHILD => e
68
+ # Don't panic
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def handler_int(signal)
75
+ for_supervisor do
76
+ @stopping = true
77
+ Sponges.logger.info "Supervisor received #{signal} signal."
78
+ kill_them_all(signal) and shutdown
79
+ end
80
+ end
81
+
82
+ alias handler_quit handler_int
83
+ alias handler_term handler_int
84
+
85
+ def kill_them_all(signal)
86
+ store.children_pids.map do |pid|
87
+ Thread.new { kill_one(pid.to_i, signal) }
88
+ end.each &:join
89
+ end
90
+
91
+ def kill_one(pid, signal)
92
+ begin
93
+ Process.kill signal, pid
94
+ Process.waitpid pid
95
+ Sponges.logger.info "Child #{pid} receive a #{signal} signal."
96
+ rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
97
+ # Don't panic
98
+ end
99
+ end
100
+
101
+ def shutdown
102
+ Process.waitall
103
+ Sponges.logger.info "Children shutdown complete.", "Supervisor shutdown. Exiting..."
104
+ store.clear(name)
105
+ exit
106
+ rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
107
+ # Don't panic
108
+ end
109
+
110
+ def fork_children
111
+ name = children_name
112
+ pid = fork do
113
+ $PROGRAM_NAME = name
114
+ (Sponges::STOP_SIGNALS + [:HUP]).each{ |sig| trap(sig) { exit!(0) } }
115
+ Sponges::Hook.after_fork
116
+ supervisor.call
117
+ end
118
+ Sponges.logger.info "Supervisor create a child with #{pid} pid."
119
+ store.add_children pid
120
+ end
121
+
122
+ def stopping?
123
+ @stopping
124
+ end
125
+ end
126
+ 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,113 +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
16
+ trap_signals
14
17
  options[:size].times do
15
- fork_children
16
- end
17
- Thread.new do
18
- trap_signals
19
- at_exit do
20
- Sponges.logger.info "Supervisor exits."
21
- end
18
+ handler.call :TTIN
22
19
  end
23
20
  Sponges.logger.info "Supervisor started, waiting for messages."
24
21
  sleep
25
22
  rescue Exception => exception
26
23
  Sponges.logger.error exception
27
- kill_them_all(:INT)
24
+ handler.call :INT
28
25
  raise exception
29
26
  end
30
27
 
31
- private
32
-
33
- def fork_children
34
- name = children_name
35
- pid = fork do
36
- $PROGRAM_NAME = name
37
- Sponges::Hook.after_fork
38
- @block.call
39
- end
40
- Sponges.logger.info "Supervisor create a child with #{pid} pid."
41
- store.add_children pid
28
+ def call
29
+ @block.call
42
30
  end
43
31
 
32
+ private
33
+
44
34
  def children_name
45
35
  "#{name}_child_#{@children_seen +=1}"
46
36
  end
47
37
 
48
38
  def trap_signals
49
- (Sponges::SIGNALS + [:HUP]).each do |signal|
50
- trap(signal) do
51
- handle_signal signal
52
- end
53
- end
54
- trap(:TTIN) do
55
- Sponges.logger.warn "Supervisor increment child's pool by one."
56
- fork_children
57
- end
58
- trap(:TTOU) do
59
- Sponges.logger.warn "Supervisor decrement child's pool by one."
60
- if store.children_pids.first
61
- kill_one(store.children_pids.first, :HUP)
62
- store.delete_children(store.children_pids.first)
63
- else
64
- Sponges.logger.warn "No more child to kill."
65
- end
66
- end
67
- trap(:CHLD) do
68
- store.children_pids.each do |pid|
69
- begin
70
- dead = Process.waitpid(pid.to_i, Process::WNOHANG)
71
- if dead
72
- Sponges.logger.warn "Child #{dead} died. Restarting a new one..."
73
- store.delete_children dead
74
- Sponges::Hook.on_chld
75
- fork_children
76
- end
77
- rescue Errno::ECHILD => e
78
- # Don't panic
79
- end
80
- end
81
- end
82
- end
83
-
84
- def handle_signal(signal)
85
- Sponges.logger.info "Supervisor received #{signal} signal."
86
- kill_them_all(signal)
87
- Process.waitall
88
- Sponges.logger.info "Children shutdown complete."
89
- Sponges.logger.info "Supervisor shutdown. Exiting..."
90
- pid = store.supervisor_pid
91
- store.clear(name)
92
- Process.kill :USR1, pid.to_i
93
- end
94
-
95
- def kill_them_all(signal)
96
- store.children_pids.each do |pid|
97
- Thread.new do
98
- kill_one(pid.to_i, signal)
99
- end
39
+ Sponges::SIGNALS.each do |signal|
40
+ trap(signal) {|signal| handler.call signal }
100
41
  end
101
42
  end
102
43
 
103
- def kill_one(pid, signal)
104
- begin
105
- Process.kill signal, pid
106
- Process.waitpid pid
107
- Sponges.logger.info "Child #{pid} receive a #{signal} signal."
108
- rescue Errno::ESRCH, Errno::ECHILD, SignalException => e
109
- # Don't panic
110
- end
111
- end
112
44
  end
113
45
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Sponges
3
- VERSION = "0.5.0.pre"
3
+ VERSION = "0.5.0"
4
4
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sponges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.pre
5
- prerelease: 6
4
+ version: 0.5.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - chatgris
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-28 00:00:00.000000000 Z
12
+ date: 2013-02-06 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
@@ -96,9 +97,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
97
  required_rubygems_version: !ruby/object:Gem::Requirement
97
98
  none: false
98
99
  requirements:
99
- - - ! '>'
100
+ - - ! '>='
100
101
  - !ruby/object:Gem::Version
101
- version: 1.3.1
102
+ version: '0'
102
103
  requirements: []
103
104
  rubyforge_project:
104
105
  rubygems_version: 1.8.24
@@ -106,3 +107,4 @@ signing_key:
106
107
  specification_version: 3
107
108
  summary: Turn any ruby object to a daemon controlling an army of sponges.
108
109
  test_files: []
110
+ has_rdoc: