kamisama 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +193 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/kamisama.gemspec +28 -0
- data/lib/kamisama.rb +94 -0
- data/lib/kamisama/process_ctrl.rb +36 -0
- data/lib/kamisama/respawn_limiter.rb +35 -0
- data/lib/kamisama/task.rb +50 -0
- data/lib/kamisama/version.rb +3 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 482b1702ced157fcca3c04db289c376857183807
|
4
|
+
data.tar.gz: 1f059faa1c65b3741ebd176f60e93658cfb7d0aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 036ead213535c5b0ccf332c88671cb3354431e21deeff00b6498a0eecde8b513d3db9e83d8753f66209bebe83ebff278f68ed4c53ed32f717ef6969608bc6f29
|
7
|
+
data.tar.gz: b316668f54aeee9358ff361c4851ab0d50de821f16147f5c5e30e9ef48309fe7a56a6eb8b5fc47c233a7083eae272fd0ea2f99b5063555f05a4e7f1fe4ab956a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Igor Šarčević
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Kamisama
|
2
|
+
|
3
|
+
[![Build Status](https://semaphoreci.com/api/v1/renderedtext/kamisama/branches/master/badge.svg)](https://semaphoreci.com/renderedtext/kamisama)
|
4
|
+
|
5
|
+
Start, monitor, and observe background worker processes, from Ruby.
|
6
|
+
|
7
|
+
Based on [Unicorn](), [God](), and [Sidekiq]().
|
8
|
+
|
9
|
+
# Usage
|
10
|
+
|
11
|
+
Kamisama is useful for starting multiple background workers. For example, let's
|
12
|
+
say that you have a background worker that crunches some data with periodic
|
13
|
+
intervals.
|
14
|
+
|
15
|
+
``` ruby
|
16
|
+
def worker
|
17
|
+
loop do
|
18
|
+
puts "Crunching data..."
|
19
|
+
|
20
|
+
sleep 60
|
21
|
+
end
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
A usual way to run this task is to wrap it in a Rake task, and an upstart script
|
26
|
+
to keep it running forever. This is pretty well until you have one process that
|
27
|
+
you want to execute. However, if you want to run multiple processes, you need to
|
28
|
+
introduce and manage multiple upstart configurations. One upstart script that
|
29
|
+
acts like the master who manages your workers, and upstart scripts that describe
|
30
|
+
your workers.
|
31
|
+
|
32
|
+
This setup is cumbersome, hard to test, and managing different configurations
|
33
|
+
for different environments (production, staging, development) can be outright
|
34
|
+
frustrating.
|
35
|
+
|
36
|
+
Kamisama is here to help, by abstracting away the issue of running and monitor
|
37
|
+
multiple background workers.
|
38
|
+
|
39
|
+
Let's run 17 instances of the above worker with Kamisama:
|
40
|
+
|
41
|
+
``` ruby
|
42
|
+
def worker(worker_index)
|
43
|
+
loop do
|
44
|
+
puts "WORKER #{worker_index}: Crunching data..."
|
45
|
+
|
46
|
+
sleep 60
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Kamisama.run(:instances => 17) { |index| worker(index) }
|
51
|
+
```
|
52
|
+
|
53
|
+
That's all! The above will start(fork) 17 processes on your machine, and restart
|
54
|
+
them in case of failure.
|
55
|
+
|
56
|
+
Keep in mind that you will still need to wrap Kamisama itself in a rake task
|
57
|
+
and an Upstart script.
|
58
|
+
|
59
|
+
### Respawn limits
|
60
|
+
|
61
|
+
Respawning workers is desirable in most cases, but we would still like to avoid
|
62
|
+
rapid restarts of your workers in a short amount of time. Such rapid restarts
|
63
|
+
can harm your system, and usually indicate that a serious issue is killing
|
64
|
+
your workers.
|
65
|
+
|
66
|
+
If the job is respawned more than `respawn_limit` times in `respawn_interval`
|
67
|
+
seconds, Kamisama will considered this to be a deeper problem and will die.
|
68
|
+
|
69
|
+
``` ruby
|
70
|
+
def worker(worker_index)
|
71
|
+
loop do
|
72
|
+
puts "WORKER #{worker_index}: Crunching data..."
|
73
|
+
|
74
|
+
sleep 60
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
config = {
|
79
|
+
:instances => 17,
|
80
|
+
:respawn_limit => 10,
|
81
|
+
:respawn_interval => 60
|
82
|
+
}
|
83
|
+
|
84
|
+
Kamisama.run(config) { |index| worker(index) }
|
85
|
+
```
|
86
|
+
|
87
|
+
## Signal control
|
88
|
+
|
89
|
+
You can control your Kamisama process by sending kill signals to the running
|
90
|
+
process.
|
91
|
+
|
92
|
+
- [TERM](#term-signal) - terminates master process and all workers
|
93
|
+
- [KILL](#kill-signal) - terminates master process and all workers
|
94
|
+
- [TTIN](#ttin-signal) - spawns a new worker
|
95
|
+
- [TTIN](#ttou-signal) - terminates a running worker
|
96
|
+
|
97
|
+
#### TERM signal
|
98
|
+
|
99
|
+
If you send a term signal to your Kamisama process, it will immediately
|
100
|
+
shutdown. Following this, every children will be notified by the kernel that the
|
101
|
+
master process has died with the TERM signal.
|
102
|
+
|
103
|
+
For example, if you have the following processes:
|
104
|
+
|
105
|
+
``` bash
|
106
|
+
2000 - PID of master process
|
107
|
+
2001 - PID of first worker
|
108
|
+
2002 - PID of second worker
|
109
|
+
2003 - PID of third worker
|
110
|
+
```
|
111
|
+
|
112
|
+
Then when you send a "TERM" signal:
|
113
|
+
|
114
|
+
``` bash
|
115
|
+
kill -TERM 2000
|
116
|
+
```
|
117
|
+
|
118
|
+
The master process `2000` will die immediately, and the workers processes
|
119
|
+
(2001, 2002, 2003) will receive the `TERM` signal.
|
120
|
+
|
121
|
+
#### KILL signal
|
122
|
+
|
123
|
+
If you send a kill signal to your Kamisama process, it will immediately
|
124
|
+
shutdown. Following this, every children will be notified by the kernel that the
|
125
|
+
master process has dies with the TERM signal.
|
126
|
+
|
127
|
+
For example, if you have the following processes:
|
128
|
+
|
129
|
+
``` bash
|
130
|
+
2000 - PID of master process
|
131
|
+
2001 - PID of first worker
|
132
|
+
2002 - PID of second worker
|
133
|
+
2003 - PID of third worker
|
134
|
+
```
|
135
|
+
|
136
|
+
Then when you send a "KILL" signal:
|
137
|
+
|
138
|
+
``` bash
|
139
|
+
kill -9 2000
|
140
|
+
```
|
141
|
+
|
142
|
+
The master process `2000` will die immediately, and the workers processes
|
143
|
+
(2001, 2002, 2003) will receive the `TERM` signal.
|
144
|
+
|
145
|
+
#### TTIN signal
|
146
|
+
|
147
|
+
If you send a ttin signal to your Kamisama process, it will spawn a new process.
|
148
|
+
|
149
|
+
For example, if you have the following processes:
|
150
|
+
|
151
|
+
``` bash
|
152
|
+
2000 - PID of master process
|
153
|
+
2001 - PID of first worker
|
154
|
+
2002 - PID of second worker
|
155
|
+
2003 - PID of third worker
|
156
|
+
```
|
157
|
+
|
158
|
+
Then when you send a "TTIN" signal:
|
159
|
+
|
160
|
+
``` bash
|
161
|
+
kill -TTIN 2000
|
162
|
+
```
|
163
|
+
|
164
|
+
The master process `2000` will spawn a new worker process.
|
165
|
+
|
166
|
+
#### TTOU signal
|
167
|
+
|
168
|
+
If you send a ttou signal to your Kamisama process, it will kill the oldest
|
169
|
+
worker.
|
170
|
+
|
171
|
+
For example, if you have the following processes:
|
172
|
+
|
173
|
+
``` bash
|
174
|
+
2000 - PID of master process
|
175
|
+
2001 - PID of first worker
|
176
|
+
2002 - PID of second worker
|
177
|
+
2003 - PID of third worker
|
178
|
+
```
|
179
|
+
|
180
|
+
Then when you send a "TTOU" signal:
|
181
|
+
|
182
|
+
``` bash
|
183
|
+
kill -TTOU 2000
|
184
|
+
```
|
185
|
+
|
186
|
+
The master process `2000` will send a `TERM` signal to the process `2001`.
|
187
|
+
|
188
|
+
*NOTE*: This will only work if you have more than one running processes.
|
189
|
+
|
190
|
+
## License
|
191
|
+
|
192
|
+
The gem is available as open source under the terms of the
|
193
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "kamisama"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/kamisama.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'kamisama/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "kamisama"
|
8
|
+
spec.version = Kamisama::VERSION
|
9
|
+
spec.authors = ["Igor Šarčević"]
|
10
|
+
spec.email = ["igor@renderedtext.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Start, monitor, and observe background worker processes, from Ruby.}
|
13
|
+
spec.description = %q{Start, monitor, and observe background worker processes, from Ruby.}
|
14
|
+
spec.homepage = "https://github.com/shiroyasha/kamisama"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "ffi", "~> 1.0"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "sys-proctable"
|
28
|
+
end
|
data/lib/kamisama.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
class Kamisama
|
2
|
+
require "kamisama/version"
|
3
|
+
require "kamisama/process_ctrl"
|
4
|
+
require "kamisama/task"
|
5
|
+
require "kamisama/respawn_limiter"
|
6
|
+
|
7
|
+
def self.run(options = {}, &block)
|
8
|
+
new(options, &block).run
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options, &block)
|
12
|
+
@block = block
|
13
|
+
@instances = options.fetch(:instances)
|
14
|
+
@respawn_limit = options.fetch(:respawn_limit, 3)
|
15
|
+
@respawn_interval = options.fetch(:respawn_interval, 60)
|
16
|
+
@monitor_sleep = 2
|
17
|
+
|
18
|
+
@term_signal_received = false
|
19
|
+
|
20
|
+
@respawn_limiter = Kamisama::RespawnLimiter.new(@respawn_limit, @respawn_interval)
|
21
|
+
|
22
|
+
@tasks = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def run
|
26
|
+
puts "[Kamisama Master] Process id: #{Process.pid}"
|
27
|
+
puts "[Kamisama Master] Starting #{@instances} workers. \n"
|
28
|
+
|
29
|
+
@instances.times { add_worker }
|
30
|
+
|
31
|
+
handle_signals
|
32
|
+
|
33
|
+
monitor
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_signals
|
37
|
+
trap("TTIN") do
|
38
|
+
@instances += 1
|
39
|
+
end
|
40
|
+
|
41
|
+
trap("TTOU") do
|
42
|
+
# make sure that we always have at least one running worker
|
43
|
+
if @instances > 1
|
44
|
+
@instances -= 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
trap("TERM") do
|
49
|
+
@term_signal_received = true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_worker
|
54
|
+
puts "[Kamisama Master] #{Process.pid} Spawning new instance."
|
55
|
+
|
56
|
+
@worker_index ||= 0
|
57
|
+
@worker_index += 1
|
58
|
+
|
59
|
+
task = Kamisama::Task.new(@worker_index, @block)
|
60
|
+
task.start
|
61
|
+
|
62
|
+
@tasks << task
|
63
|
+
end
|
64
|
+
|
65
|
+
def term_worker
|
66
|
+
puts "[Kamisama Master] #{Process.pid} Terminating an instance."
|
67
|
+
|
68
|
+
task = @tasks.shift
|
69
|
+
task.terminate!
|
70
|
+
end
|
71
|
+
|
72
|
+
def monitor
|
73
|
+
loop do
|
74
|
+
break if @term_signal_received
|
75
|
+
|
76
|
+
add_worker while @tasks.count < @instances
|
77
|
+
term_worker while @tasks.count > @instances
|
78
|
+
|
79
|
+
dead_tasks = @tasks.reject(&:alive?)
|
80
|
+
|
81
|
+
dead_tasks.each do |task|
|
82
|
+
@respawn_limiter.record!
|
83
|
+
task.restart!
|
84
|
+
end
|
85
|
+
|
86
|
+
sleep(@monitor_sleep)
|
87
|
+
end
|
88
|
+
|
89
|
+
puts "[Kamisama Master] #{Process.pid} Terminating all instances"
|
90
|
+
@tasks.each(&:terminate!)
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "ffi"
|
2
|
+
|
3
|
+
class Kamisama
|
4
|
+
class ProcessCtrl
|
5
|
+
SIGINT = 2
|
6
|
+
SIGTERM = 15
|
7
|
+
|
8
|
+
module LibC
|
9
|
+
PR_SET_NAME = 15
|
10
|
+
PR_SET_PDEATHSIG = 1
|
11
|
+
|
12
|
+
extend FFI::Library
|
13
|
+
ffi_lib "c"
|
14
|
+
attach_function :prctl, [:int, :long, :long, :long, :long], :int
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.set_process_name(process_name)
|
18
|
+
# The process name is max 16 characters, so get the first 16, and if it is
|
19
|
+
# less pad with spaces to avoid formatting wierdness
|
20
|
+
process_name = "%-16.16s" % name
|
21
|
+
|
22
|
+
LibC.prctl(LibC::PR_SET_NAME, process_name, 0, 0, 0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.set_parent_death_signal(signal)
|
26
|
+
case signal
|
27
|
+
when :sigint
|
28
|
+
LibC.prctl(LibC::PR_SET_PDEATHSIG, SIGINT, 0, 0, 0)
|
29
|
+
when :sigterm
|
30
|
+
LibC.prctl(LibC::PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0)
|
31
|
+
else
|
32
|
+
raise "Unrecognized signal '#{signal.inspect}'"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Kamisama::RespawnLimiter
|
2
|
+
|
3
|
+
def initialize(respawn_limit, respawn_interval)
|
4
|
+
@respawn_limit = respawn_limit
|
5
|
+
@respawn_interval = respawn_interval
|
6
|
+
|
7
|
+
@respawns = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def record!
|
11
|
+
now = Time.now.to_i
|
12
|
+
|
13
|
+
@respawns = @respawns.select { |timestamp| timestamp >= now - @respawn_interval } + [now]
|
14
|
+
|
15
|
+
die_if_breached!
|
16
|
+
end
|
17
|
+
|
18
|
+
def calculate_respawn_count
|
19
|
+
now = Time.now.to_i
|
20
|
+
|
21
|
+
@respawns.count { |timestamp| timestamp > (now - @respawn_interval) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def die_if_breached!
|
25
|
+
respawn_count = calculate_respawn_count
|
26
|
+
|
27
|
+
if respawn_count >= @respawn_limit
|
28
|
+
puts "[Kamisama Master] Respawn count #{respawn_count} hit the limit of #{@respawn_limit} for the respawn interval of #{@respawn_interval} seconds."
|
29
|
+
puts "[Kamisama Master] Terminating."
|
30
|
+
|
31
|
+
exit(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Kamisama
|
2
|
+
class Task
|
3
|
+
def initialize(task_index, block)
|
4
|
+
@task_index = task_index
|
5
|
+
@block = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def start
|
9
|
+
@pid = Process.fork do
|
10
|
+
begin
|
11
|
+
# receive sigterm when parent dies
|
12
|
+
Kamisama::ProcessCtrl.set_parent_death_signal(:sigterm)
|
13
|
+
|
14
|
+
log("Worker started. Hello!")
|
15
|
+
|
16
|
+
@block.call(@task_index)
|
17
|
+
rescue Exception => e
|
18
|
+
# handle all exceptions, even system ones
|
19
|
+
log("Shutting down... #{e.message}")
|
20
|
+
exit
|
21
|
+
ensure
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Process.detach(@pid)
|
27
|
+
end
|
28
|
+
|
29
|
+
def restart!
|
30
|
+
puts "[Kamisama Master] Restarting Worker."
|
31
|
+
@pid = nil
|
32
|
+
start
|
33
|
+
end
|
34
|
+
|
35
|
+
def terminate!
|
36
|
+
Process.kill("TERM", @pid)
|
37
|
+
end
|
38
|
+
|
39
|
+
def alive?
|
40
|
+
Process.getpgid(@pid)
|
41
|
+
true
|
42
|
+
rescue Errno::ESRCH
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def log(message)
|
47
|
+
puts "[WORKER #{@task_index}] #{message}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kamisama
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Igor Šarčević
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sys-proctable
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Start, monitor, and observe background worker processes, from Ruby.
|
84
|
+
email:
|
85
|
+
- igor@renderedtext.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- CODE_OF_CONDUCT.md
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/console
|
98
|
+
- bin/setup
|
99
|
+
- kamisama.gemspec
|
100
|
+
- lib/kamisama.rb
|
101
|
+
- lib/kamisama/process_ctrl.rb
|
102
|
+
- lib/kamisama/respawn_limiter.rb
|
103
|
+
- lib/kamisama/task.rb
|
104
|
+
- lib/kamisama/version.rb
|
105
|
+
homepage: https://github.com/shiroyasha/kamisama
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.4.8
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Start, monitor, and observe background worker processes, from Ruby.
|
129
|
+
test_files: []
|