trident 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDRhNzEyMDc3ZGY3NGM3MDAzMzNkNWJmYTM5ODUxOTA4OTljN2YyMg==
5
- data.tar.gz: !binary |-
6
- MjQ2YWVmMzAwZjEzNTUwZTkwNzJlOGU3YzNhMjc4ZTNlNTU2ZTdhYw==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZTc0NGI3MjljOTg4YzI1MDhkMDg0YWVjNTUxY2ZiYjkxN2YyMDkyMGRhYzZm
10
- MDRjMmQ4MDA0MmRjMGVjNmM2NWI1OTMwNDUyYTU2ZWE1YjI2MjA3YjZkN2Zm
11
- NzY3NWZkZWJiYTBiODM5Njk4MDU1MWZmMGVjOTc3OTk0YmRhZDI=
12
- data.tar.gz: !binary |-
13
- NTljZGRhZDc2NDBkYmVjYjkzZGM2OTM0M2Q0NmYzYWNlZjc3MmYxNzFkM2Uy
14
- YWNkMWIxMzM4MzhkOTBmODVjNjkyMzliOWMyYTUyOTFmMTk3OWJlZTQ0Mjgy
15
- NjllMmJlZjkyN2U3NWM4NzlhNjNhZDhjOGVjODZiZjY5ZDMyNDk=
2
+ SHA1:
3
+ metadata.gz: c1497896041247b078fad1afd3814676a75819c7
4
+ data.tar.gz: 7fc6cc36f0a02b4088270ed5466e67d2f33b8bdd
5
+ SHA512:
6
+ metadata.gz: c462d1e488d09b3779dee1c44a378aaf65ea41f8b283fe98fcf091d1e351dd6a8150ff11e61bf26396f110de13b718d39db3d31c4da1eb0b584daf5201172fb6
7
+ data.tar.gz: a2686b40f96950edc600388daa311487c08f932666524b4c050b2bd9cfd70ae5ed6baa0f3217b26fd8c15d82e262343aa7d78c6ef60f9dfafdf562d0157ba659
@@ -2,7 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - jruby-19mode
6
- - rbx-19mode
5
+ # - rbx-19mode
7
6
 
8
7
  script: bundle exec rake
@@ -0,0 +1,10 @@
1
+ 0.2.0 (11/18/2013)
2
+ ------------------
3
+
4
+ prevent environment from stealing cli log <0947a63> [Matt Conway]
5
+
6
+
7
+ 0.1.0 (11/05/2013)
8
+ ------------------
9
+
10
+ Initial version
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Trident
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/wr0ngway/trident.png)](http://travis-ci.org/wr0ngway/trident)
4
+ [![Coverage Status](https://coveralls.io/repos/wr0ngway/trident/badge.png?branch=master)](https://coveralls.io/r/wr0ngway/trident?branch=master)
5
+
3
6
  A ruby gem for managing pools of forked workers
4
7
 
5
8
  ## Installation
@@ -25,9 +28,11 @@ After installing the gem, use the 'trident' binary to generate an example config
25
28
  Edit the file with your desired setup, then run trident to launch all your worker pools
26
29
 
27
30
  See other command line options with
31
+
28
32
  trident --help
29
33
 
30
34
 
31
35
  ## TODO
32
36
 
33
37
  * Add support for reloading the trident config with a HUP signal
38
+ * Add support in yml for specifying [process limits](http://www.ruby-doc.org/core-1.9.3/Process.html#method-c-setrlimit) (memory especially)
@@ -3,6 +3,13 @@
3
3
 
4
4
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
5
 
6
+ # setup gemlogger before loading our classes so they use
7
+ # our logger, and it doesn't get overridden by a preloaded
8
+ # client environment
9
+ require 'gem_logger'
10
+ require 'trident/cli_logger'
11
+ GemLogger.logger_concern = Trident::CLILogger
12
+
6
13
  require 'trident'
7
14
  Trident::CLI.run
8
15
 
@@ -1,6 +1,7 @@
1
1
  require 'clamp'
2
2
  require 'erb'
3
3
  require 'yaml'
4
+ require 'trident/cli_logger'
4
5
 
5
6
  module Trident
6
7
  class CLI < Clamp::Command
@@ -44,8 +45,8 @@ module Trident
44
45
  self.pidfile = expand_path(pidfile)
45
46
  self.config = expand_path(config)
46
47
 
47
- GemLogger.default_logger = Logger.new(logfile ? logfile : STDOUT)
48
- GemLogger.default_logger.level = verbose? ? Logger::DEBUG : Logger::INFO
48
+ Trident::CLILogger.trident_logger = Logger.new(logfile ? logfile : STDOUT)
49
+ Trident::CLILogger.trident_logger.level = verbose? ? Logger::DEBUG : Logger::INFO
49
50
  $stdout.sync = $stderr.sync = true
50
51
 
51
52
  if daemon? && (logfile.nil? || pidfile.nil?)
@@ -89,7 +90,9 @@ module Trident
89
90
 
90
91
  # Configure through yaml file
91
92
  def load_config(path_to_yaml_file)
92
- config = YAML::load(ERB.new(IO.read(path_to_yaml_file)).result)
93
+ erb = ERB.new(IO.read(path_to_yaml_file))
94
+ erb.filename = path_to_yaml_file
95
+ config = YAML::load(erb.result)
93
96
  config = config[Rails.env.to_s] if defined?(::Rails) && config.has_key?(Rails.env.to_s)
94
97
  config
95
98
  end
@@ -0,0 +1,23 @@
1
+ # setup our own logger for cli so that we don't lose it when
2
+ # we preload environment for workers
3
+ module Trident
4
+ module CLILogger
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ def self.trident_logger
9
+ @trident_logger ||= ::Logger.new(STDOUT)
10
+ end
11
+
12
+ def self.trident_logger=(logger)
13
+ @trident_logger = logger
14
+ end
15
+
16
+ module ClassMethods
17
+ def logger
18
+ Trident::CLILogger.trident_logger
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -50,8 +50,9 @@ module Trident
50
50
  loop do
51
51
  signal_result = handle_signal_queue
52
52
  break if signal_result == :break
53
+ logger.debug "Snoozing main loop"
53
54
  msg = snooze if signal_queue.empty?
54
- logger.debug "Main loop awake"
55
+ logger.debug "Main loop awakened: #{msg.inspect}"
55
56
  break if msg == MSG_STOP
56
57
  end
57
58
  logger.info "Main loop exited"
@@ -81,7 +82,6 @@ module Trident
81
82
  def snooze
82
83
  msg = ""
83
84
  begin
84
- logger.info "Snoozing main loop"
85
85
  ready = IO.select([self_pipe.first], nil, nil, 1) or return
86
86
  ready.first && ready.first.first or return
87
87
  loop { msg << self_pipe.first.read_nonblock(CHUNK_SIZE) }
@@ -1,3 +1,3 @@
1
1
  module Trident
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,44 @@
1
+ # a name for labelling pool processes
2
+ application: app_name
3
+
4
+ # loads handlers in the master process before forking workers
5
+ prefork: true
6
+
7
+ # Configure the behavior of the pool manager in response to signals
8
+ # actions are methods on PoolManager and can be sequenced
9
+ signals:
10
+ INT: stop_gracefully
11
+ TERM: stop_forcefully
12
+ USR1: [stop_forcefully, wait]
13
+
14
+ # define and setup all the PoolHandlers
15
+ handlers:
16
+ myhandler:
17
+ environment: |+
18
+ require 'gem_logger'
19
+ GemLogger.default_logger = Logger.new("/dev/null")
20
+ class MyWorker
21
+ def initialize(o)
22
+ @o = o
23
+ end
24
+ def start
25
+ loop { sleep 1 }
26
+ end
27
+ end
28
+ class: MyWorker
29
+ options:
30
+ signals:
31
+ default: USR2
32
+ stop_gracefully: INT
33
+ stop_forcefully: TERM
34
+
35
+ # Configure the worker pools
36
+ pools:
37
+ mypool1:
38
+ # number of worker processes
39
+ size: 2
40
+ # chooses a handler defined above for running process
41
+ handler: myhandler
42
+ # options passed to each handler's initializer (merged into handler options above)
43
+ options:
44
+ name: one
@@ -7,28 +7,6 @@ class Trident::TridentTest < MiniTest::Should::TestCase
7
7
  @cli = "#{File.expand_path('../../..', __FILE__)}/bin/trident"
8
8
  end
9
9
 
10
- def wait_for(io, pattern)
11
- timeout(5) do
12
- loop do
13
- line = io.readline
14
- puts line if ENV['DEBUG']
15
- break if line =~ pattern
16
- end
17
- end
18
- end
19
-
20
- def process_list
21
- processes = {}
22
- lines = `ps -e -opid,command`.lines.grep(/trident\[/)
23
- lines.each do |line|
24
- pieces = line.split
25
- pid = pieces[0].to_i
26
- next if pid == Process.pid
27
- command = pieces[1..-1].join(' ')
28
- processes[pid] = command
29
- end
30
- processes
31
- end
32
10
 
33
11
  def parse_manager(manager_str)
34
12
  pools = {}
@@ -48,7 +26,7 @@ class Trident::TridentTest < MiniTest::Should::TestCase
48
26
  wait_for(io, /<pool-mypool1> Pool started with 3 workers/)
49
27
  wait_for(io, /<pool-mypool2> Pool started with 2 workers/)
50
28
 
51
- processes = process_list
29
+ processes = child_processes
52
30
  assert_equal 6, processes.size
53
31
  manager = processes[io.pid]
54
32
  pools = parse_manager(manager)
@@ -66,7 +44,7 @@ class Trident::TridentTest < MiniTest::Should::TestCase
66
44
  wait_for(io, /Main loop exited/)
67
45
 
68
46
  Process.wait(io.pid)
69
- assert_empty process_list
47
+ assert_empty child_processes
70
48
  end
71
49
 
72
50
  end
@@ -80,7 +58,7 @@ class Trident::TridentTest < MiniTest::Should::TestCase
80
58
  wait_for(io, /<pool-mypool1> Pool started with 3 workers/)
81
59
  wait_for(io, /<pool-mypool2> Pool started with 2 workers/)
82
60
 
83
- processes = process_list
61
+ processes = child_processes
84
62
  assert_equal 6, processes.size
85
63
  manager = processes[io.pid]
86
64
  pools = parse_manager(manager)
@@ -89,7 +67,7 @@ class Trident::TridentTest < MiniTest::Should::TestCase
89
67
  Process.kill("KILL", child)
90
68
 
91
69
  wait_for(io, /<pool-mypool1> Spawned worker \d+, worker count now at 3/)
92
- processes = process_list
70
+ processes = child_processes
93
71
  assert_equal 6, processes.size
94
72
  manager = processes[io.pid]
95
73
  pools = parse_manager(manager)
@@ -98,7 +76,7 @@ class Trident::TridentTest < MiniTest::Should::TestCase
98
76
 
99
77
  Process.kill("USR1", io.pid)
100
78
  Process.wait(io.pid)
101
- assert_empty process_list
79
+ assert_empty child_processes
102
80
  end
103
81
 
104
82
  end
@@ -1,9 +1,9 @@
1
1
  require 'rubygems'
2
2
 
3
- if ENV['CI']
4
- require 'coveralls'
5
- Coveralls.wear!
6
- end
3
+ #if ENV['CI']
4
+ # require 'coveralls'
5
+ # Coveralls.wear!
6
+ #end
7
7
 
8
8
  require 'bundler'
9
9
  begin
@@ -93,11 +93,46 @@ class FileCounter
93
93
 
94
94
  end
95
95
 
96
+ def wait_for(io, pattern)
97
+ timeout(5) do
98
+ loop do
99
+ line = io.readline
100
+ puts line if ENV['DEBUG']
101
+ break if line =~ pattern
102
+ end
103
+ end
104
+ end
105
+
106
+ def child_processes(pid=Process.pid)
107
+ processes = {}
108
+ lines = `pstree -w #{pid}`.lines.to_a
109
+ # lines = `ps -g #{pid} -opid,command`.lines.to_a
110
+ lines.shift # get rid of header
111
+ lines.each do |line|
112
+ pieces = line.scan(/\A[^\d]*(\d+) \w+ (.*)\Z/).first
113
+ pid = pieces.shift
114
+ pid = pid.to_i
115
+ raise "Failed to extract pid: #{line} - #{pieces}" if pid == 0
116
+ next if pid == Process.pid
117
+
118
+ command = pieces.shift.strip
119
+ next if command =~ /^ps/
120
+ processes[pid] = command
121
+ end
122
+ processes
123
+ end
124
+
125
+ def kill_all_child_processes
126
+ child_processes.keys.each {|p| Process.kill("KILL", p) rescue nil }
127
+ Process.waitall
128
+ end
129
+
96
130
  class MiniTest::Should::TestCase
97
131
  ORIGINAL_PROCLINE = $0
98
132
 
99
133
  setup do
100
134
  $0 = ORIGINAL_PROCLINE
135
+ kill_all_child_processes
101
136
  end
102
137
  end
103
138
 
@@ -24,6 +24,20 @@ class Trident::CLITest < MiniTest::Should::TestCase
24
24
 
25
25
  end
26
26
 
27
+ context "#logging" do
28
+
29
+ should "keep own logger when preforking" do
30
+ # Make sure cli keeps log when preforked environment replaces GemLogger.basic_logger
31
+ cmd = "#{@cli} --config #{@project_root}/test/fixtures/trident_logging.yml"
32
+ io = IO.popen(cmd, :err=>[:child, :out])
33
+ wait_for(io, /<pool-mypool1> Pool started with 2 workers/)
34
+
35
+ Process.kill("TERM", io.pid)
36
+ Process.wait(io.pid)
37
+ end
38
+
39
+ end
40
+
27
41
  context "#project_root" do
28
42
 
29
43
  should "use bundler env for root" do
@@ -8,11 +8,12 @@ class Trident::UtilsTest < MiniTest::Should::TestCase
8
8
  should "set the procline of the process" do
9
9
  pid = fork do
10
10
  procline "foo", "bar"
11
+ sleep 1
11
12
  end
12
-
13
- process_name = `ps -o command -p #{pid}`.lines.to_a.last.strip
13
+ process_name = child_processes[pid]
14
14
  assert_equal "trident[foo]: bar", process_name
15
15
  Process.kill("KILL", pid)
16
+ Process.waitall
16
17
  end
17
18
 
18
19
  end
metadata CHANGED
@@ -1,52 +1,52 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trident
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Conway
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-05 00:00:00.000000000 Z
11
+ date: 2013-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_logger
15
- prerelease: false
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - ! '>='
17
+ - - '>='
19
18
  - !ruby/object:Gem::Version
20
19
  version: '0'
21
20
  type: :runtime
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: clamp
29
- prerelease: false
30
29
  requirement: !ruby/object:Gem::Requirement
31
30
  requirements:
32
- - - ! '>='
31
+ - - '>='
33
32
  - !ruby/object:Gem::Version
34
33
  version: '0'
35
34
  type: :runtime
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
- prerelease: false
44
43
  requirement: !ruby/object:Gem::Requirement
45
44
  requirements:
46
45
  - - ~>
47
46
  - !ruby/object:Gem::Version
48
47
  version: '1.3'
49
48
  type: :development
49
+ prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
@@ -54,58 +54,58 @@ dependencies:
54
54
  version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
- prerelease: false
58
57
  requirement: !ruby/object:Gem::Requirement
59
58
  requirements:
60
- - - ! '>='
59
+ - - '>='
61
60
  - !ruby/object:Gem::Version
62
61
  version: '0'
63
62
  type: :development
63
+ prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- prerelease: false
72
71
  requirement: !ruby/object:Gem::Requirement
73
72
  requirements:
74
- - - ! '>='
73
+ - - '>='
75
74
  - !ruby/object:Gem::Version
76
75
  version: '0'
77
76
  type: :development
77
+ prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: minitest_should
85
- prerelease: false
86
85
  requirement: !ruby/object:Gem::Requirement
87
86
  requirements:
88
- - - ! '>='
87
+ - - '>='
89
88
  - !ruby/object:Gem::Version
90
89
  version: '0'
91
90
  type: :development
91
+ prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: minitest-reporters
99
- prerelease: false
100
99
  requirement: !ruby/object:Gem::Requirement
101
100
  requirements:
102
- - - ! '>='
101
+ - - '>='
103
102
  - !ruby/object:Gem::Version
104
103
  version: '0'
105
104
  type: :development
105
+ prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ! '>='
108
+ - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  description: Manages pools of forked ruby processes
@@ -119,6 +119,7 @@ files:
119
119
  - .coveralls.yml
120
120
  - .gitignore
121
121
  - .travis.yml
122
+ - CHANGELOG
122
123
  - Gemfile
123
124
  - LICENSE.txt
124
125
  - README.md
@@ -126,6 +127,7 @@ files:
126
127
  - bin/trident
127
128
  - lib/trident.rb
128
129
  - lib/trident/cli.rb
130
+ - lib/trident/cli_logger.rb
129
131
  - lib/trident/pool.rb
130
132
  - lib/trident/pool_handler.rb
131
133
  - lib/trident/pool_manager.rb
@@ -133,6 +135,7 @@ files:
133
135
  - lib/trident/utils.rb
134
136
  - lib/trident/version.rb
135
137
  - test/fixtures/integration_project/config/trident.yml
138
+ - test/fixtures/trident_logging.yml
136
139
  - test/integration/trident_test.rb
137
140
  - test/test_helper.rb
138
141
  - test/unit/trident/cli_test.rb
@@ -153,22 +156,23 @@ require_paths:
153
156
  - lib
154
157
  required_ruby_version: !ruby/object:Gem::Requirement
155
158
  requirements:
156
- - - ! '>='
159
+ - - '>='
157
160
  - !ruby/object:Gem::Version
158
161
  version: '0'
159
162
  required_rubygems_version: !ruby/object:Gem::Requirement
160
163
  requirements:
161
- - - ! '>='
164
+ - - '>='
162
165
  - !ruby/object:Gem::Version
163
166
  version: '0'
164
167
  requirements: []
165
168
  rubyforge_project:
166
- rubygems_version: 2.0.7
169
+ rubygems_version: 2.0.6
167
170
  signing_key:
168
171
  specification_version: 4
169
172
  summary: Manages pools of forked ruby processes
170
173
  test_files:
171
174
  - test/fixtures/integration_project/config/trident.yml
175
+ - test/fixtures/trident_logging.yml
172
176
  - test/integration/trident_test.rb
173
177
  - test/test_helper.rb
174
178
  - test/unit/trident/cli_test.rb