sponges 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +28 -8
- data/lib/sponges.rb +3 -1
- data/lib/sponges/cli.rb +10 -0
- data/lib/sponges/commander.rb +38 -10
- data/lib/sponges/configuration.rb +9 -1
- data/lib/sponges/runner.rb +6 -18
- data/lib/sponges/store.rb +15 -0
- data/lib/sponges/store/memory.rb +65 -0
- data/lib/sponges/store/redis.rb +74 -0
- data/lib/sponges/supervisor.rb +18 -30
- data/lib/sponges/version.rb +1 -1
- metadata +5 -18
data/README.md
CHANGED
@@ -22,7 +22,7 @@ Internally, `sponges` strongly relies on Unix signals.
|
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
25
|
-
Ruby 1.9.2 (or superior)
|
25
|
+
Ruby 1.9.2 (or superior).
|
26
26
|
|
27
27
|
Install it with rubygems:
|
28
28
|
|
@@ -66,15 +66,14 @@ Sponges.configure do |config|
|
|
66
66
|
config.size = 3
|
67
67
|
config.daemonize = true
|
68
68
|
config.after_fork do
|
69
|
-
puts "Execute
|
69
|
+
puts "Execute code when a child process is created"
|
70
70
|
end
|
71
71
|
config.on_chld do
|
72
72
|
puts "Execute code when a child process is killed"
|
73
73
|
end
|
74
74
|
|
75
75
|
# Register a pool named "worker_name".
|
76
|
-
#
|
77
|
-
# the precedence.
|
76
|
+
#
|
78
77
|
Sponges.start "worker_name" do
|
79
78
|
Worker.new({some: args}).run
|
80
79
|
end
|
@@ -99,9 +98,10 @@ Start 8 instances of the worker and daemonize them:
|
|
99
98
|
ruby example.rb start -d -s 8 # By default, size equals cpu core's size.
|
100
99
|
```
|
101
100
|
|
102
|
-
Retart gracefully 4 instances of the worker
|
101
|
+
Retart gracefully 4 instances of the worker, with a timeout of 3 seconds and
|
102
|
+
daemonize them:
|
103
103
|
``` bash
|
104
|
-
ruby example.rb restart -g -d -s 4
|
104
|
+
ruby example.rb restart -g -d -s 4 -t 3
|
105
105
|
```
|
106
106
|
|
107
107
|
Stop workers with a `QUIT` signal :
|
@@ -116,10 +116,12 @@ ruby example.rb kill
|
|
116
116
|
|
117
117
|
Stop workers with a `HUP` signal :
|
118
118
|
``` bash
|
119
|
-
ruby example.rb stop -g
|
119
|
+
ruby example.rb stop -g -t 5
|
120
120
|
```
|
121
121
|
In this case, you will have to trap the `HUP` signal, and handle a clean stop
|
122
|
-
from each workers. The point is to wait for a task to be done before quitting.
|
122
|
+
from each workers. The point is to wait for a task to be done before quitting. A
|
123
|
+
timeout can be specify with the `-t` option. When this timeout is hited, the
|
124
|
+
process is killed.
|
123
125
|
|
124
126
|
Increment worker's pool size :
|
125
127
|
``` bash
|
@@ -136,6 +138,24 @@ Show a list of workers and their children.
|
|
136
138
|
ruby example.rb list
|
137
139
|
```
|
138
140
|
|
141
|
+
## Stores
|
142
|
+
|
143
|
+
sponges can store pids in memory or in redis. Memory is the default store. The
|
144
|
+
`list` command is not available with the memory store.
|
145
|
+
|
146
|
+
To select the redis store, you need to add `nest` to your application's
|
147
|
+
Gemfile, and do the following.
|
148
|
+
|
149
|
+
``` ruby
|
150
|
+
gem "sponges"
|
151
|
+
```
|
152
|
+
|
153
|
+
``` ruby
|
154
|
+
Sponges.configure do |config|
|
155
|
+
config.store = :redis
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
139
159
|
## Acknowledgements
|
140
160
|
|
141
161
|
sponges would not have been the same without [Jesse
|
data/lib/sponges.rb
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
require 'boson/runner'
|
3
3
|
require 'socket'
|
4
4
|
require 'logger'
|
5
|
-
require 'nest'
|
6
5
|
require 'machine'
|
7
6
|
require_relative 'sponges/configuration'
|
8
7
|
require_relative 'sponges/supervisor'
|
9
8
|
require_relative 'sponges/runner'
|
10
9
|
require_relative 'sponges/commander'
|
11
10
|
require_relative 'sponges/cli'
|
11
|
+
require_relative 'sponges/store'
|
12
|
+
require_relative 'sponges/store/memory'
|
13
|
+
require_relative 'sponges/store/redis'
|
12
14
|
|
13
15
|
module Sponges
|
14
16
|
SIGNALS = [:INT, :QUIT, :TERM]
|
data/lib/sponges/cli.rb
CHANGED
@@ -17,8 +17,13 @@ module Sponges
|
|
17
17
|
end
|
18
18
|
|
19
19
|
option :gracefully, type: :boolean
|
20
|
+
option :timeout, type: :numeric
|
20
21
|
desc "Stop workers"
|
21
22
|
def stop(options = {})
|
23
|
+
options = {
|
24
|
+
timeout: Sponges::Configuration.timeout,
|
25
|
+
gracefully: Sponges::Configuration.gracefully
|
26
|
+
}.reject{|k, v| v.nil?}.merge(options)
|
22
27
|
Sponges::Commander.new(Sponges::Configuration.worker_name, options).stop
|
23
28
|
end
|
24
29
|
|
@@ -30,6 +35,7 @@ module Sponges
|
|
30
35
|
option :daemonize, type: :boolean
|
31
36
|
option :size, type: :numeric
|
32
37
|
option :gracefully, type: :boolean
|
38
|
+
option :timeout, type: :numeric
|
33
39
|
desc "Restart workers"
|
34
40
|
def restart(options = {})
|
35
41
|
stop(options)
|
@@ -50,6 +56,10 @@ module Sponges
|
|
50
56
|
|
51
57
|
desc "Show running processes"
|
52
58
|
def list
|
59
|
+
if Sponges::Configuration.store == :memory
|
60
|
+
puts "Command not available with the memory store"
|
61
|
+
exit
|
62
|
+
end
|
53
63
|
redis = Nest.new('sponges')
|
54
64
|
puts %q{
|
55
65
|
___ _ __ ___ _ __ __ _ ___ ___
|
data/lib/sponges/commander.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'timeout'
|
3
|
+
|
2
4
|
module Sponges
|
3
5
|
# This class concern is to send messages to supervisor. It's used to send
|
4
6
|
# messages like 'stop' or 'restart'
|
5
7
|
#
|
6
8
|
class Commander
|
9
|
+
attr_reader :store
|
10
|
+
|
7
11
|
def initialize(name, options = {})
|
8
12
|
@name, @options = name, options
|
9
|
-
@
|
13
|
+
@store = Sponges::Store.new(@name)
|
10
14
|
end
|
11
15
|
|
12
16
|
# Kills the supervisor, and then all workers.
|
@@ -14,8 +18,14 @@ module Sponges
|
|
14
18
|
def kill
|
15
19
|
Sponges.logger.info "Runner #{@name} kill message received."
|
16
20
|
stop :KILL
|
17
|
-
|
18
|
-
|
21
|
+
children_pids.each do|pid|
|
22
|
+
begin
|
23
|
+
kill_process(:KILL, pid, "Worker")
|
24
|
+
rescue Errno::ESRCH => e
|
25
|
+
# Don't panic
|
26
|
+
ensure
|
27
|
+
store.delete_children pid
|
28
|
+
end
|
19
29
|
end
|
20
30
|
end
|
21
31
|
|
@@ -24,8 +34,18 @@ module Sponges
|
|
24
34
|
def stop(signal = nil)
|
25
35
|
signal ||= gracefully? ? :HUP : :QUIT
|
26
36
|
Sponges.logger.info "Runner #{@name} stop message received."
|
27
|
-
if pid =
|
28
|
-
|
37
|
+
if pid = supervisor_pid
|
38
|
+
if @options[:timeout]
|
39
|
+
begin
|
40
|
+
Timeout::timeout(@options[:timeout]) do
|
41
|
+
kill_process(signal, pid)
|
42
|
+
end
|
43
|
+
rescue Timeout::Error
|
44
|
+
kill
|
45
|
+
end
|
46
|
+
else
|
47
|
+
kill_process(signal, pid)
|
48
|
+
end
|
29
49
|
else
|
30
50
|
Sponges.logger.info "No supervisor found."
|
31
51
|
end
|
@@ -35,9 +55,9 @@ module Sponges
|
|
35
55
|
#
|
36
56
|
def increment
|
37
57
|
Sponges.logger.info "Runner #{@name} increment message received."
|
38
|
-
if pid =
|
58
|
+
if pid = supervisor_pid
|
39
59
|
begin
|
40
|
-
Process.kill :TTIN,
|
60
|
+
Process.kill :TTIN, supervisor.to_i
|
41
61
|
rescue Errno::ESRCH => e
|
42
62
|
Sponges.logger.error e
|
43
63
|
end
|
@@ -50,9 +70,9 @@ module Sponges
|
|
50
70
|
#
|
51
71
|
def decrement
|
52
72
|
Sponges.logger.info "Runner #{@name} decrement message received."
|
53
|
-
if
|
73
|
+
if supervisor_pid
|
54
74
|
begin
|
55
|
-
Process.kill :TTOU,
|
75
|
+
Process.kill :TTOU, supervisor_pid.to_i
|
56
76
|
rescue Errno::ESRCH => e
|
57
77
|
Sponges.logger.error e
|
58
78
|
end
|
@@ -63,6 +83,14 @@ module Sponges
|
|
63
83
|
|
64
84
|
private
|
65
85
|
|
86
|
+
def supervisor_pid
|
87
|
+
@store.supervisor_pid
|
88
|
+
end
|
89
|
+
|
90
|
+
def children_pids
|
91
|
+
@store.children_pids
|
92
|
+
end
|
93
|
+
|
66
94
|
def kill_process(signal, pid, type = "Supervisor")
|
67
95
|
pid = pid.to_i
|
68
96
|
begin
|
@@ -73,7 +101,7 @@ module Sponges
|
|
73
101
|
end
|
74
102
|
Sponges.logger.info "#{type} #{pid} has stopped."
|
75
103
|
rescue Errno::ESRCH => e
|
76
|
-
|
104
|
+
# Don't panic
|
77
105
|
end
|
78
106
|
end
|
79
107
|
|
@@ -5,7 +5,7 @@ module Sponges
|
|
5
5
|
class Configuration
|
6
6
|
class << self
|
7
7
|
ACCESSOR = [:worker_name, :worker, :logger, :redis, :size,
|
8
|
-
:daemonize, :after_fork
|
8
|
+
:daemonize, :after_fork, :timeout, :gracefully, :store
|
9
9
|
]
|
10
10
|
attr_accessor *ACCESSOR
|
11
11
|
|
@@ -27,6 +27,14 @@ module Sponges
|
|
27
27
|
def on_chld(&block)
|
28
28
|
Hook._on_chld = block
|
29
29
|
end
|
30
|
+
|
31
|
+
def store
|
32
|
+
@store || :memory
|
33
|
+
end
|
34
|
+
|
35
|
+
def redis
|
36
|
+
@redis ||= Redis.new
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
data/lib/sponges/runner.rb
CHANGED
@@ -4,15 +4,17 @@ module Sponges
|
|
4
4
|
# watch over the supervisor.
|
5
5
|
#
|
6
6
|
class Runner
|
7
|
+
attr_reader :store
|
8
|
+
|
7
9
|
def initialize(name, options = {}, block)
|
8
10
|
@name, @block = name, block
|
9
11
|
@options = default_options.merge options
|
10
|
-
@
|
11
|
-
if running?
|
12
|
+
@store = Sponges::Store.new(@name)
|
13
|
+
if store.running?
|
12
14
|
Sponges.logger.error "Runner #{@name} already started."
|
13
15
|
exit
|
14
16
|
end
|
15
|
-
|
17
|
+
store.register_hostname Socket.gethostname
|
16
18
|
end
|
17
19
|
|
18
20
|
def start
|
@@ -29,20 +31,6 @@ module Sponges
|
|
29
31
|
|
30
32
|
private
|
31
33
|
|
32
|
-
def running?
|
33
|
-
if pid = @redis[Socket.gethostname][:worker][@name][:supervisor].get
|
34
|
-
begin
|
35
|
-
Process.kill 0, pid.to_i
|
36
|
-
true
|
37
|
-
rescue Errno::ESRCH => e
|
38
|
-
@redis[Socket.gethostname][:worker][@name][:supervisor].del
|
39
|
-
false
|
40
|
-
end
|
41
|
-
else
|
42
|
-
false
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
34
|
def trap_signals
|
47
35
|
Sponges::SIGNALS.each do |signal|
|
48
36
|
trap(signal) {|signal| kill_supervisor(signal) }
|
@@ -63,7 +51,7 @@ module Sponges
|
|
63
51
|
def fork_supervisor
|
64
52
|
fork do
|
65
53
|
$PROGRAM_NAME = "#{@name}_supervisor"
|
66
|
-
Supervisor.new(@name, @options, @block).start
|
54
|
+
Supervisor.new(@name, @options, store, @block).start
|
67
55
|
end
|
68
56
|
end
|
69
57
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Sponges
|
5
|
+
class Store
|
6
|
+
class Memory
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_writer :supervisor_pid
|
10
|
+
attr_reader :pids, :name
|
11
|
+
|
12
|
+
def initialize(name)
|
13
|
+
@pids, @name = [], name
|
14
|
+
end
|
15
|
+
|
16
|
+
def_delegator :@pids, :<<, :add_children
|
17
|
+
def_delegator :@pids, :delete, :delete_children
|
18
|
+
|
19
|
+
def supervisor_pid
|
20
|
+
return @supervisor_pid if @supervisor_pid
|
21
|
+
s = find_supervisor
|
22
|
+
@supervisor_pid = s.pid if s
|
23
|
+
end
|
24
|
+
|
25
|
+
def children_pids
|
26
|
+
@pids.any? ? @pids : find_childs.map(&:pid)
|
27
|
+
end
|
28
|
+
|
29
|
+
def running?
|
30
|
+
!!find_supervisor
|
31
|
+
end
|
32
|
+
|
33
|
+
def register(supervisor_pid)
|
34
|
+
@supervisor_pid = supervisor_pid
|
35
|
+
end
|
36
|
+
|
37
|
+
def register_hostname(hostname)
|
38
|
+
end
|
39
|
+
|
40
|
+
def on_fork
|
41
|
+
end
|
42
|
+
|
43
|
+
def clear
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def supervisor_name
|
49
|
+
"#{name}_supervisor"
|
50
|
+
end
|
51
|
+
|
52
|
+
def childs_name
|
53
|
+
"#{name}_child"
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_supervisor
|
57
|
+
Sys::ProcTable.ps.select {|f| f.cmdline == supervisor_name }.first
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_childs
|
61
|
+
Sys::ProcTable.ps.select {|f| f.cmdline =~ /^#{childs_name}/ }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Sponges
|
3
|
+
class Store
|
4
|
+
class Redis
|
5
|
+
attr_reader :redis, :hostname_store, :name
|
6
|
+
private :redis, :hostname_store
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
@redis ||= Nest.new('sponges', Configuration.redis)
|
11
|
+
@hostname_store = @redis[Socket.gethostname]
|
12
|
+
end
|
13
|
+
|
14
|
+
def supervisor_pid
|
15
|
+
hostname_store[:worker][name][:supervisor].get
|
16
|
+
end
|
17
|
+
|
18
|
+
def children_pids
|
19
|
+
Array(hostname_store[:worker][name][:pids].smembers)
|
20
|
+
end
|
21
|
+
|
22
|
+
def running?
|
23
|
+
if pid = hostname_store[:worker][name][:supervisor].get
|
24
|
+
begin
|
25
|
+
Process.kill 0, pid.to_i
|
26
|
+
true
|
27
|
+
rescue Errno::ESRCH => e
|
28
|
+
hostname_store[:worker][name][:supervisor].del
|
29
|
+
false
|
30
|
+
end
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def register_hostname(hostname)
|
37
|
+
redis[:hostnames].sadd hostname
|
38
|
+
end
|
39
|
+
|
40
|
+
def register(supervisor_pid)
|
41
|
+
hostname_store[:workers].sadd name
|
42
|
+
hostname_store[:worker][name][:supervisor].set supervisor_pid
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_children(pid)
|
46
|
+
hostname_store[:worker][name][:pids].sadd pid
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_children(pid)
|
50
|
+
hostname_store[:worker][name][:pids].srem pid
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear(name)
|
54
|
+
hostname_store[:worker][name][:supervisor].del
|
55
|
+
hostname_store[:workers].srem name
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_fork
|
59
|
+
Sponges::Configuration.redis.client.reconnect
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def find_supervisor
|
65
|
+
Sys::ProcTable.ps.select {|f| f.cmdline == supervisor_name }.first
|
66
|
+
end
|
67
|
+
|
68
|
+
def find_childs
|
69
|
+
Sys::ProcTable.ps.select {|f| f.cmdline =~ /^#{childs_name}/ }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/sponges/supervisor.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Sponges
|
3
3
|
class Supervisor
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@
|
4
|
+
attr_reader :store, :name, :options
|
5
|
+
|
6
|
+
def initialize(name, options, store, block)
|
7
|
+
@name, @options, @store, @block = name, options, store, block
|
8
|
+
store.on_fork
|
9
|
+
store.register Process.pid
|
8
10
|
@children_seen = 0
|
9
11
|
end
|
10
12
|
|
11
13
|
def start
|
12
|
-
|
14
|
+
options[:size].times do
|
13
15
|
fork_children
|
14
16
|
end
|
15
17
|
trap_signals
|
@@ -22,16 +24,6 @@ module Sponges
|
|
22
24
|
|
23
25
|
private
|
24
26
|
|
25
|
-
def set_up_redis
|
26
|
-
if Configuration.redis
|
27
|
-
redis_client = Configuration.redis
|
28
|
-
redis_client.client.reconnect
|
29
|
-
end
|
30
|
-
@redis = Nest.new('sponges', redis_client || Redis.new)[Socket.gethostname]
|
31
|
-
@redis[:workers].sadd @name
|
32
|
-
@redis[:worker][@name][:supervisor].set Process.pid
|
33
|
-
end
|
34
|
-
|
35
27
|
def fork_children
|
36
28
|
name = children_name
|
37
29
|
pid = fork do
|
@@ -40,11 +32,11 @@ module Sponges
|
|
40
32
|
@block.call
|
41
33
|
end
|
42
34
|
Sponges.logger.info "Supervisor create a child with #{pid} pid."
|
43
|
-
|
35
|
+
store.add_children pid
|
44
36
|
end
|
45
37
|
|
46
38
|
def children_name
|
47
|
-
"#{
|
39
|
+
"#{name}_child_#{@children_seen +=1}"
|
48
40
|
end
|
49
41
|
|
50
42
|
def trap_signals
|
@@ -59,19 +51,19 @@ module Sponges
|
|
59
51
|
end
|
60
52
|
trap(:TTOU) do
|
61
53
|
Sponges.logger.warn "Supervisor decrement child's pool by one."
|
62
|
-
if
|
63
|
-
kill_one(
|
54
|
+
if store.children_pids.first
|
55
|
+
kill_one(store.children_pids.first, :HUP)
|
64
56
|
else
|
65
57
|
Sponges.logger.warn "No more child to kill."
|
66
58
|
end
|
67
59
|
end
|
68
60
|
trap(:CHLD) do
|
69
|
-
|
61
|
+
store.children_pids.each do |pid|
|
70
62
|
begin
|
71
63
|
dead = Process.waitpid(pid.to_i, Process::WNOHANG)
|
72
64
|
if dead
|
73
65
|
Sponges.logger.warn "Child #{dead} died. Restarting a new one..."
|
74
|
-
|
66
|
+
store.delete_children dead
|
75
67
|
Sponges::Hook.on_chld
|
76
68
|
fork_children
|
77
69
|
end
|
@@ -88,30 +80,26 @@ module Sponges
|
|
88
80
|
Process.waitall
|
89
81
|
Sponges.logger.info "Children shutdown complete."
|
90
82
|
Sponges.logger.info "Supervisor shutdown. Exiting..."
|
91
|
-
pid =
|
92
|
-
|
93
|
-
@redis[:workers].srem @name
|
83
|
+
pid = store.supervisor_pid
|
84
|
+
store.clear(name)
|
94
85
|
Process.kill :USR1, pid.to_i
|
95
86
|
end
|
96
87
|
|
97
88
|
def kill_them_all(signal)
|
98
|
-
|
89
|
+
store.children_pids.each do |pid|
|
99
90
|
kill_one(pid, signal)
|
100
91
|
end
|
101
92
|
end
|
102
93
|
|
103
94
|
def kill_one(pid, signal)
|
104
95
|
begin
|
105
|
-
@pids.srem pid
|
106
96
|
Process.kill signal, pid.to_i
|
97
|
+
Process.waitpid pid.to_i
|
98
|
+
store.delete_children pid
|
107
99
|
Sponges.logger.info "Child #{pid} receive a #{signal} signal."
|
108
100
|
rescue Errno::ESRCH => e
|
109
101
|
# Don't panic
|
110
102
|
end
|
111
103
|
end
|
112
|
-
|
113
|
-
def pids
|
114
|
-
Array(@pids.smembers)
|
115
|
-
end
|
116
104
|
end
|
117
105
|
end
|
data/lib/sponges/version.rb
CHANGED
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.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
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: 2012-
|
12
|
+
date: 2012-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: boson
|
@@ -27,22 +27,6 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: nest
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '0'
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: machine
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,6 +76,9 @@ files:
|
|
92
76
|
- lib/sponges/commander.rb
|
93
77
|
- lib/sponges/configuration.rb
|
94
78
|
- lib/sponges/runner.rb
|
79
|
+
- lib/sponges/store.rb
|
80
|
+
- lib/sponges/store/memory.rb
|
81
|
+
- lib/sponges/store/redis.rb
|
95
82
|
- lib/sponges/supervisor.rb
|
96
83
|
- lib/sponges/version.rb
|
97
84
|
homepage: https://github.com/AF83/sponges
|