phantom-manager 0.0.2
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.
- checksums.yaml +15 -0
- data/.DS_Store +0 -0
- data/.gitignore +3 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/bin/phantom_monitor +55 -0
- data/config/config.yml +27 -0
- data/lib/.DS_Store +0 -0
- data/lib/monitors/base.rb +39 -0
- data/lib/monitors/memory.rb +27 -0
- data/lib/monitors/processes.rb +33 -0
- data/lib/monitors/restart_listener.rb +39 -0
- data/lib/monitors/violations_recorders/base.rb +56 -0
- data/lib/monitors/violations_recorders/memory.rb +23 -0
- data/lib/monitors/violations_recorders/processes.rb +21 -0
- data/lib/nginx/manager.rb +59 -0
- data/lib/phantom/.DS_Store +0 -0
- data/lib/phantom/collector.rb +36 -0
- data/lib/phantom/manager/version.rb +5 -0
- data/lib/phantom/manager.rb +34 -0
- data/lib/phantom/process.rb +54 -0
- data/lib/utils/cfg.rb +18 -0
- data/lib/utils/limited_array.rb +31 -0
- data/lib/utils/lock.rb +29 -0
- data/lib/utils/logger.rb +3 -0
- data/lib/utils/shell.rb +12 -0
- data/phantom-manager.gemspec +24 -0
- data/spec/files/config.yml +12 -0
- data/spec/files/nginx.conf +26 -0
- data/spec/lib/monitors/base_spec.rb +14 -0
- data/spec/lib/monitors/memory_spec.rb +33 -0
- data/spec/lib/monitors/processes_spec.rb +45 -0
- data/spec/lib/monitors/restart_listener_spec.rb +27 -0
- data/spec/lib/monitors/violations_recorders/base_spec.rb +126 -0
- data/spec/lib/monitors/violations_recorders/memory_spec.rb +73 -0
- data/spec/lib/monitors/violations_recorders/processes_spec.rb +51 -0
- data/spec/lib/nginx/manager_spec.rb +80 -0
- data/spec/lib/phantom/collector_spec.rb +59 -0
- data/spec/lib/phantom/manager_spec.rb +25 -0
- data/spec/lib/phantom/process_spec.rb +47 -0
- data/spec/lib/utils/limited_array_spec.rb +73 -0
- data/spec/lib/utils/lock_spec.rb +69 -0
- data/spec/lib/utils/shell_spec.rb +18 -0
- data/spec/shared_spec.rb +45 -0
- data/spec/spec_helper.rb +29 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmU1OGFhZGQzODQ2NGJkNjkwN2FkNmM3ZWI0NTE3ZWI4NWY5NzEzNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGJjMTI5Yzk1NjVkOTczM2E4MWEyMWM2NGMxMmQ2NmUzMTdmYjM4MQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjI3NTQwNDNjMWVmZGRkYzk3NTYzZmE5MDE4YmFiNjkwNGFjMmJmMTkxOWE0
|
10
|
+
ODQ1MTRlYzY3NjFmMzg0MjZiZGM5ODIyOWY2NWY0NjgyNWQ0M2UyZTI1NDcx
|
11
|
+
MDMxZmUzZTM0OTVlMzFmYWVkNGI5MGNiZDVjNzEyYTU2Yjk3MmE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzdkODY4MjYyNDc4MzFmYjlhNTc2NGE2MDg5MmMwOWI2ZTA4ZjI4ZTkwYTA2
|
14
|
+
YTU2OTdlMjI4MmJlNmUyZmEyYzAxOWE5ZWQyMzQzZDdiNWRmYWFmNWM5ODRj
|
15
|
+
ZDJiYjUzNTU4YzcyYmYyZTlhZTdiZmEzZDhmOGUzYTQwZjcyMGQ=
|
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
phantom-manager (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
columnize (0.3.6)
|
10
|
+
debugger (1.4.0)
|
11
|
+
columnize (>= 0.3.1)
|
12
|
+
debugger-linecache (~> 1.1.1)
|
13
|
+
debugger-ruby_core_source (~> 1.2.0)
|
14
|
+
debugger-linecache (1.1.2)
|
15
|
+
debugger-ruby_core_source (>= 1.1.1)
|
16
|
+
debugger-ruby_core_source (1.2.0)
|
17
|
+
diff-lcs (1.2.4)
|
18
|
+
rake (10.1.0)
|
19
|
+
rspec (2.14.1)
|
20
|
+
rspec-core (~> 2.14.0)
|
21
|
+
rspec-expectations (~> 2.14.0)
|
22
|
+
rspec-mocks (~> 2.14.0)
|
23
|
+
rspec-core (2.14.3)
|
24
|
+
rspec-expectations (2.14.0)
|
25
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
26
|
+
rspec-mocks (2.14.1)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bundler (~> 1.3)
|
33
|
+
debugger
|
34
|
+
phantom-manager!
|
35
|
+
rake
|
36
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Erez Rabih
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Phantom::Manager
|
2
|
+
|
3
|
+
phantom-manager allows you to use multiple phantom-js processes behind an Nginx
|
4
|
+
server. It will manage both presence and memory consumption of those processes
|
5
|
+
and kill them when appropriate, all this in sync with the Nginx configuration
|
6
|
+
so that all requests will get answered.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'phantom-manager'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install phantom-manager
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
TODO: Write usage instructions here
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Fork it
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
32
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/phantom_monitor
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
$options = {}
|
6
|
+
|
7
|
+
optparse = OptionParser.new do |opts|
|
8
|
+
|
9
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
10
|
+
puts opts
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on( '-c', '--config FILE', "Configuration file path" ) do |f|
|
15
|
+
$options[:config] = f
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on( '-e', '--env ENVIRONMENT', "Environment to run on" ) do |env|
|
19
|
+
$options[:env] = env
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
optparse.parse!
|
25
|
+
|
26
|
+
mandatory = [:env, :config]
|
27
|
+
missing = mandatory.select{ |param| $options[param].nil? }
|
28
|
+
|
29
|
+
if not missing.empty?
|
30
|
+
puts "Missing options: #{missing.join(', ')}"
|
31
|
+
puts optparse
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
lib = File.expand_path('../../lib', __FILE__)
|
36
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
37
|
+
|
38
|
+
require 'phantom/manager/version'
|
39
|
+
require 'monitors/memory.rb'
|
40
|
+
require 'monitors/processes.rb'
|
41
|
+
require 'monitors/restart_listener.rb'
|
42
|
+
|
43
|
+
|
44
|
+
$logger.info "Starting for environment #{$options[:env]} with config file #{$options[:config]}... "
|
45
|
+
|
46
|
+
Monitors::RestartListener.run
|
47
|
+
|
48
|
+
$logger.info "Running memory monitor for phantom processes"
|
49
|
+
|
50
|
+
Thread.new {Monitors::Memory.run}
|
51
|
+
|
52
|
+
$logger.info "Running processes monitor for phantom processes"
|
53
|
+
|
54
|
+
Thread.new {Monitors::Processes.run}.join
|
55
|
+
|
data/config/config.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
development:
|
2
|
+
#The time to wait between removing a phantomjs from the nginx configuration
|
3
|
+
#and actually killing the process.
|
4
|
+
phantom_termination_grace: 10
|
5
|
+
|
6
|
+
#This will be the inital port of the phantomjs processes. For example if
|
7
|
+
#phantom_processes_number is set to 4 and phantom_base_port to 8000 then 4
|
8
|
+
#phantoms, on ports 8000 8001 8002 8003 will be managed.
|
9
|
+
phantom_base_port: 8002
|
10
|
+
#Rails root path
|
11
|
+
rails_root: "path"
|
12
|
+
#Path to your nginx configuration
|
13
|
+
nginx_conf: "path"
|
14
|
+
#Path to where you want to keep your phantomjs logs
|
15
|
+
phantom_log_path: "path"
|
16
|
+
#If a phantom process memory consumption is over memory_limit for
|
17
|
+
#memory_retries times with memory_check_interval between each check it will
|
18
|
+
#be killed
|
19
|
+
memory_limit: 150000
|
20
|
+
memory_retries: 5
|
21
|
+
memory_check_interval: 5
|
22
|
+
#Number of phantom processes to keep up. If a process is missing for
|
23
|
+
#processes_check_retries times in a row with processes_check_interval between
|
24
|
+
#checks it will be brought up byt the monitor
|
25
|
+
phantom_processes_number: 10
|
26
|
+
processes_check_retries: 3
|
27
|
+
processes_check_interval: 15
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'utils/cfg'
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'phantom/manager'
|
4
|
+
require 'phantom/collector'
|
5
|
+
|
6
|
+
module Monitors
|
7
|
+
class Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def run(custom_logger = $logger)
|
11
|
+
@logger = custom_logger
|
12
|
+
|
13
|
+
loop do
|
14
|
+
perform_check
|
15
|
+
sleep check_interval
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def perform_check
|
22
|
+
raise NotImplementedError.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_interval
|
26
|
+
raise NotImplementedError.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def running_instances
|
30
|
+
Phantom::Collector.get_running_instances
|
31
|
+
end
|
32
|
+
|
33
|
+
def logger
|
34
|
+
@logger ||= $logger
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'monitors/base'
|
2
|
+
require 'monitors/violations_recorders/memory'
|
3
|
+
|
4
|
+
module Monitors
|
5
|
+
class Memory < Base
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def perform_check
|
10
|
+
logger.info "Perfoming memory check..."
|
11
|
+
|
12
|
+
running_instances.each do |p|
|
13
|
+
if ViolationsRecorders::Memory.is_violating?(p)
|
14
|
+
logger.info "process #{p.pid} was found bad!"
|
15
|
+
Phantom::Manager.restart(p)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_interval
|
22
|
+
$cfg.memory_check_interval
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'monitors/base'
|
2
|
+
require 'monitors/violations_recorders/processes'
|
3
|
+
|
4
|
+
module Monitors
|
5
|
+
class Processes < Base
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def perform_check
|
9
|
+
logger.info "Perfoming processes check..."
|
10
|
+
|
11
|
+
missing_processes = Phantom::Collector.missing_ports.map do |port|
|
12
|
+
p = Phantom::Process.new
|
13
|
+
p.port = port
|
14
|
+
p
|
15
|
+
end
|
16
|
+
|
17
|
+
missing_processes.each do |p|
|
18
|
+
if ViolationsRecorders::Processes.is_violating?(p)
|
19
|
+
logger.info "found missing phantom on port #{p.port}"
|
20
|
+
Phantom::Manager.start(p)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
logger.info "All processes are running OK" if missing_processes.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_interval
|
28
|
+
$cfg.processes_check_interval
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'phantom/manager'
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'utils/cfg'
|
4
|
+
require 'utils/lock'
|
5
|
+
|
6
|
+
|
7
|
+
module Monitors
|
8
|
+
class RestartListener
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def run
|
12
|
+
Signal.trap("USR2") do
|
13
|
+
respond_to_signal
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to_signal
|
18
|
+
lock.acquire do
|
19
|
+
$logger.info "Initiating restart sequence"
|
20
|
+
|
21
|
+
Phantom::Collector.get_running_instances.each do |p|
|
22
|
+
$logger.info "Restarting process on port #{p.port}"
|
23
|
+
Phantom::Manager.restart(p)
|
24
|
+
|
25
|
+
sleep $cfg.phantom_termination_grace
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def lock
|
34
|
+
@lock ||= Utils::Lock.new
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
require 'phantom/process'
|
4
|
+
|
5
|
+
module Monitors
|
6
|
+
module ViolationsRecorders
|
7
|
+
class Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def inherited(base)
|
12
|
+
base.instance_variable_set(:@violations, {})
|
13
|
+
end
|
14
|
+
|
15
|
+
@violations = {}
|
16
|
+
|
17
|
+
def reset
|
18
|
+
@violations = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_violating?(process)
|
22
|
+
$logger.debug "checking #{process}"
|
23
|
+
update_violations_count(process)
|
24
|
+
$logger.debug "#{@violations}"
|
25
|
+
violating = @violations[process.send(process_attr)] == retries_limit
|
26
|
+
@violations[process.send(process_attr)] = 0 if violating
|
27
|
+
violating
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def update_violations_count(process)
|
33
|
+
@violations[process.send(process_attr)] ||= 0
|
34
|
+
if process_is_violating?(process)
|
35
|
+
@violations[process.send(process_attr)]+= 1
|
36
|
+
else
|
37
|
+
@violations[process.send(process_attr)] = 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def retries_limit
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_attr
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
|
49
|
+
def process_is_violating?(process)
|
50
|
+
raise NotImplementedError
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'monitors/violations_recorders/base'
|
2
|
+
|
3
|
+
module Monitors
|
4
|
+
module ViolationsRecorders
|
5
|
+
class Memory < Base
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def retries_limit
|
9
|
+
$cfg.memory_retries
|
10
|
+
end
|
11
|
+
|
12
|
+
def process_attr
|
13
|
+
:pid
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_is_violating?(process)
|
17
|
+
process.memory_usage > $cfg.memory_limit
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'monitors/violations_recorders/base'
|
2
|
+
|
3
|
+
module Monitors
|
4
|
+
module ViolationsRecorders
|
5
|
+
class Processes < Base
|
6
|
+
class << self
|
7
|
+
def retries_limit
|
8
|
+
$cfg.processes_check_retries
|
9
|
+
end
|
10
|
+
|
11
|
+
def process_attr
|
12
|
+
:port
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_is_violating?(process)
|
16
|
+
Phantom::Collector.missing_ports.include?(process.port)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
|
4
|
+
module Nginx
|
5
|
+
class Manager
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def remove(port)
|
9
|
+
$logger.info "removing #{port} from nginx"
|
10
|
+
modify_nginx do |ofile, iline|
|
11
|
+
ofile.puts(iline) unless iline =~ /#{port}/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(port)
|
16
|
+
$logger.info "adding #{port} to nginx"
|
17
|
+
if !port_defined?(port)
|
18
|
+
modify_nginx do |ofile, iline|
|
19
|
+
ofile.puts(iline)
|
20
|
+
ofile.puts(phantom_upstream(port)) if iline =~ /upstream phantomjs/
|
21
|
+
end
|
22
|
+
else
|
23
|
+
$logger.info "port #{port} already defined"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def phantom_upstream(port)
|
30
|
+
" server 127.0.0.1:#{port} fail_timeout=0; # #{Time.now}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def port_defined?(port)
|
34
|
+
File.readlines($cfg.nginx_conf).grep(/#{port}/).size > 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def switch_nginx_configs
|
38
|
+
$logger.info "switching nginx configurations"
|
39
|
+
`mv #{$cfg.new_nginx_conf} #{$cfg.nginx_conf}`
|
40
|
+
end
|
41
|
+
|
42
|
+
def reload_nginx
|
43
|
+
$logger.info "reloading nginx"
|
44
|
+
`nginx -s reload`
|
45
|
+
end
|
46
|
+
|
47
|
+
def modify_nginx
|
48
|
+
File.open($cfg.new_nginx_conf, "w") do |ofile|
|
49
|
+
File.foreach($cfg.nginx_conf) do |iline|
|
50
|
+
yield ofile, iline
|
51
|
+
end
|
52
|
+
end
|
53
|
+
switch_nginx_configs
|
54
|
+
reload_nginx
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'phantom/process'
|
2
|
+
|
3
|
+
module Phantom
|
4
|
+
class Collector
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def on_port(port)
|
8
|
+
get_running_instances.find {|p| p.port == port}
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_running_instances
|
12
|
+
lines = running_phantoms_shell_output.split("\n")
|
13
|
+
lines.map {|l| Phantom::Process.from_string(l) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def missing_ports
|
17
|
+
required_ports - get_running_instances.map(&:port)
|
18
|
+
end
|
19
|
+
|
20
|
+
def required_ports
|
21
|
+
($cfg.phantom_base_port..($cfg.phantom_base_port+$cfg.phantom_processes_number-1)).to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def running_phantoms_shell_output
|
27
|
+
`#{running_phantoms_shell_command}`
|
28
|
+
end
|
29
|
+
|
30
|
+
def running_phantoms_shell_command
|
31
|
+
"ps -e -www -o pid,rss,command | grep 'phantomjs' | grep -v sh | grep -v grep"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "phantom/manager/version"
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'utils/cfg'
|
4
|
+
require 'nginx/manager'
|
5
|
+
|
6
|
+
module Phantom
|
7
|
+
module Manager
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def restart(process)
|
11
|
+
$logger.info "restarting process #{process}"
|
12
|
+
stop process
|
13
|
+
start process
|
14
|
+
end
|
15
|
+
|
16
|
+
def start(process)
|
17
|
+
$logger.info "starting process #{process.port}"
|
18
|
+
process.start
|
19
|
+
Nginx::Manager.add(process.port)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def stop(process)
|
25
|
+
$logger.info "stopping process #{process}"
|
26
|
+
Nginx::Manager.remove(process.port)
|
27
|
+
sleep $cfg.phantom_termination_grace
|
28
|
+
process.kill
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
require 'utils/shell'
|
4
|
+
|
5
|
+
module Phantom
|
6
|
+
class Process
|
7
|
+
attr_accessor :pid, :memory_usage, :command, :port
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def from_string(str)
|
12
|
+
args = parse_string(str)
|
13
|
+
new(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parse_string(str)
|
19
|
+
parts = str.split
|
20
|
+
pid = parts[0].to_i
|
21
|
+
memory_usage = parts[1].to_i
|
22
|
+
command = parts[2..-1].join(" ")
|
23
|
+
port = parts.last.to_i
|
24
|
+
|
25
|
+
[pid, memory_usage, command, port]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(pid = nil, memory_usage = nil, command = nil, port = nil)
|
31
|
+
@pid = pid
|
32
|
+
@memory_usage = memory_usage
|
33
|
+
@command = command
|
34
|
+
@port = port
|
35
|
+
end
|
36
|
+
|
37
|
+
def kill
|
38
|
+
$logger.info "killing #{self}"
|
39
|
+
Utils::Shell.execute "kill #{pid}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def start
|
43
|
+
$logger.info "starting phantomjs on port #{port}"
|
44
|
+
Utils::Shell.execute start_command
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def start_command
|
50
|
+
"cd #{$cfg.rails_root} && phantomjs rndrme.js #{port} >>#{$cfg.phantom_log_path} 2>&1 &"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/utils/cfg.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class Cfg
|
5
|
+
def self.load
|
6
|
+
cfg = File.expand_path($options[:config])
|
7
|
+
env = $options[:env]
|
8
|
+
hash = YAML.load(File.open(cfg))[env]
|
9
|
+
hash.each do |k,v|
|
10
|
+
hash[k] = v.to_i if v =~ /^\d+$/
|
11
|
+
end
|
12
|
+
obj = OpenStruct.new hash
|
13
|
+
obj.new_nginx_conf = "#{obj.nginx_conf}.new"
|
14
|
+
|
15
|
+
$cfg = obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Cfg.load
|