sponges 0.5.0 → 0.5.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
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