sponges 0.5.0 → 0.5.0.1.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/README.md CHANGED
@@ -1,10 +1,5 @@
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
-
8
3
  When I build workers, I want them to be like an army of spongebobs, always
9
4
  stressed and eager to work. `sponges` helps you build this army of sponges, to
10
5
  control them, and, well, to kill them gracefully. Making them stressed and eager
data/lib/sponges.rb CHANGED
@@ -3,9 +3,7 @@ require 'boson/runner'
3
3
  require 'socket'
4
4
  require 'logger'
5
5
  require 'machine'
6
- require 'forwardable'
7
6
  require_relative 'sponges/configuration'
8
- require_relative 'sponges/handler'
9
7
  require_relative 'sponges/supervisor'
10
8
  require_relative 'sponges/runner'
11
9
  require_relative 'sponges/commander'
@@ -15,8 +13,7 @@ require_relative 'sponges/store/memory'
15
13
  require_relative 'sponges/store/redis'
16
14
 
17
15
  module Sponges
18
- STOP_SIGNALS = [:INT, :QUIT, :TERM]
19
- SIGNALS = STOP_SIGNALS + [:HUP, :TTIN, :TTOU, :CHLD]
16
+ SIGNALS = [:INT, :QUIT, :TERM]
20
17
 
21
18
  def configure(&block)
22
19
  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?
@@ -50,6 +50,7 @@ module Sponges
50
50
 
51
51
  def fork_supervisor
52
52
  fork do
53
+ $PROGRAM_NAME = "#{@name}_supervisor"
53
54
  Supervisor.new(@name, @options, store, @block).start
54
55
  end
55
56
  end
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ require 'forwardable'
3
+
2
4
  module Sponges
3
5
  class Store
4
6
  class Memory
@@ -1,45 +1,111 @@
1
1
  # encoding: utf-8
2
2
  module Sponges
3
3
  class Supervisor
4
- attr_reader :store, :name, :options, :handler
4
+ attr_reader :store, :name, :options
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"
9
8
  store.on_fork
10
9
  store.register Process.pid
11
10
  @children_seen = 0
12
- @handler = Handler.new self
13
11
  end
14
12
 
15
13
  def start
16
14
  trap_signals
15
+ at_exit do
16
+ Sponges.logger.info "Supervisor exits."
17
+ end
17
18
  options[:size].times do
18
- handler.call :TTIN
19
+ fork_children
19
20
  end
20
21
  Sponges.logger.info "Supervisor started, waiting for messages."
21
22
  sleep
22
23
  rescue Exception => exception
23
24
  Sponges.logger.error exception
24
- handler.call :INT
25
+ kill_them_all(:INT)
25
26
  raise exception
26
27
  end
27
28
 
28
- def call
29
- @block.call
30
- end
31
-
32
29
  private
33
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
41
+ end
42
+
34
43
  def children_name
35
44
  "#{name}_child_#{@children_seen +=1}"
36
45
  end
37
46
 
38
47
  def trap_signals
39
- Sponges::SIGNALS.each do |signal|
40
- trap(signal) {|signal| handler.call signal }
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)
41
98
  end
42
99
  end
43
100
 
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
44
110
  end
45
111
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Sponges
3
- VERSION = "0.5.0"
3
+ VERSION = "0.5.0.1.pre"
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
5
- prerelease:
4
+ version: 0.5.0.1.pre
5
+ prerelease: 8
6
6
  platform: ruby
7
7
  authors:
8
8
  - chatgris
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: boson
@@ -75,7 +75,6 @@ files:
75
75
  - lib/sponges/cli.rb
76
76
  - lib/sponges/commander.rb
77
77
  - lib/sponges/configuration.rb
78
- - lib/sponges/handler.rb
79
78
  - lib/sponges/runner.rb
80
79
  - lib/sponges/store.rb
81
80
  - lib/sponges/store/memory.rb
@@ -97,9 +96,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
96
  required_rubygems_version: !ruby/object:Gem::Requirement
98
97
  none: false
99
98
  requirements:
100
- - - ! '>='
99
+ - - ! '>'
101
100
  - !ruby/object:Gem::Version
102
- version: '0'
101
+ version: 1.3.1
103
102
  requirements: []
104
103
  rubyforge_project:
105
104
  rubygems_version: 1.8.24
@@ -107,4 +106,3 @@ signing_key:
107
106
  specification_version: 3
108
107
  summary: Turn any ruby object to a daemon controlling an army of sponges.
109
108
  test_files: []
110
- has_rdoc:
@@ -1,126 +0,0 @@
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