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 +0 -5
- data/lib/sponges.rb +1 -4
- data/lib/sponges/commander.rb +1 -1
- data/lib/sponges/runner.rb +1 -0
- data/lib/sponges/store/memory.rb +2 -0
- data/lib/sponges/supervisor.rb +77 -11
- data/lib/sponges/version.rb +1 -1
- metadata +5 -7
- data/lib/sponges/handler.rb +0 -126
data/README.md
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
# sponges
|
2
2
|
|
3
|
-
[](https://codeclimate.com/github/AF83/sponges)
|
5
|
-
[](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
|
-
|
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
|
data/lib/sponges/commander.rb
CHANGED
data/lib/sponges/runner.rb
CHANGED
data/lib/sponges/store/memory.rb
CHANGED
data/lib/sponges/supervisor.rb
CHANGED
@@ -1,45 +1,111 @@
|
|
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
|
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
|
-
|
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
|
-
|
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)
|
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
|
data/lib/sponges/version.rb
CHANGED
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-
|
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:
|
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:
|
data/lib/sponges/handler.rb
DELETED
@@ -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
|