resque-pool-diet 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Changelog.md +73 -0
- data/LICENSE.txt +20 -0
- data/README.md +155 -0
- data/Rakefile +30 -0
- data/bin/resque-pool +7 -0
- data/features/basic_daemon_config.feature +68 -0
- data/features/step_definitions/daemon_steps.rb +33 -0
- data/features/step_definitions/resque-pool_steps.rb +155 -0
- data/features/support/aruba_daemon_support.rb +76 -0
- data/features/support/env.rb +1 -0
- data/lib/resque/pool/cli.rb +120 -0
- data/lib/resque/pool/logging.rb +65 -0
- data/lib/resque/pool/pooled_worker.rb +21 -0
- data/lib/resque/pool/tasks.rb +20 -0
- data/lib/resque/pool/version.rb +5 -0
- data/lib/resque/pool.rb +342 -0
- data/man/resque-pool.1 +79 -0
- data/man/resque-pool.1.ronn +77 -0
- data/man/resque-pool.yml.5 +46 -0
- data/man/resque-pool.yml.5.ronn +41 -0
- data/spec/mock_config.rb +6 -0
- data/spec/resque-pool.yml +13 -0
- data/spec/resque_pool_spec.rb +134 -0
- data/spec/spec_helper.rb +3 -0
- metadata +191 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dbc3dc56f138c2f095d7c5993fe2dc4536f2c62e
|
4
|
+
data.tar.gz: c2587117f353f7725098d1ed1519d4dd66902bb3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c5bdbd0d6dcfc0474e4c6134283e351faf0d0d34ca896e89cede6f23f8fb72cd9f9e70635844508595b54a573f1c4801513176150a600234aeef0eb7838cc0db
|
7
|
+
data.tar.gz: 386474a58efb5ee5d545faaf39a69cd478c5463b7127d6548c183c919e72c3fb18fbbe07b84e8d7dc02503be06c1371a2716298e1a5b2b3df9aee404a8079a38
|
data/Changelog.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
## 0.3.0 (2012-??-??)
|
2
|
+
|
3
|
+
This is mostly just a long overdue maintenance release. Many pull requests were
|
4
|
+
merged. A few non-pull-request branches were merged too. This version supports
|
5
|
+
ruby 1.9.3, 1.8.7, and even ancient 1.8.6, and all are checked by
|
6
|
+
[travis-ci](http://travis-ci.org/nevans/resque-pool). It also explicitly
|
7
|
+
supports resque ~> 1.20. And (if you have `gem-man` installed), it now has man
|
8
|
+
pages for bin and yml config.
|
9
|
+
|
10
|
+
Many thanks to the contributers!
|
11
|
+
|
12
|
+
* [@agnellvj](https://github.com/agnellvj): ruby 1.9 compatibility
|
13
|
+
* [@geoffgarside](https://github.com/geoffgarside): man pages!
|
14
|
+
* [@imajes](https://github.com/imajes) - bugfix: Handle when a pid no longer
|
15
|
+
exists by the time you try and kill it.
|
16
|
+
* [@jeremy](https://github.com/jeremy) & [@jamis](https://github.com/jamis) -
|
17
|
+
tasks require `resque/pool` lazily
|
18
|
+
* [@jhsu](https://github.com/jhsu) - bugfix: undefined variable 'e' for errors
|
19
|
+
* [@gaffneyc](https://github.com/gaffneyc) - compatibility fix:
|
20
|
+
Resque::Pool::PooledWorker as a module rather than class
|
21
|
+
* [@kcrayon](https://github.com/kcrayon) - bugfix: fix worker shutdown
|
22
|
+
* [@alexkwolfe](https://github.com/alexkwolfe) - added `app_name` for logging
|
23
|
+
(and maybe more in the future?)
|
24
|
+
|
25
|
+
## 0.2.0 (2011-03-15)
|
26
|
+
|
27
|
+
* new feature: sending `HUP` to pool manager will reload the logfiles and
|
28
|
+
gracefully restart all workers.
|
29
|
+
* enhancement: logging now includes timestamp, process "name" (worker or
|
30
|
+
manager), and PID.
|
31
|
+
* enhancement: can be used with no config file or empty config file (not all
|
32
|
+
*that* useful, but it's better than unceromoniously dieing!)
|
33
|
+
* bugfix: pidfile will be cleaned up on startup, e.g. if old process was
|
34
|
+
kill-9'd (Jason Haruska)
|
35
|
+
* bugfix: TERM/INT are no longer ignored when HUP is waiting on children
|
36
|
+
* bugfix: `resque-pool -c config.yml` command line option was broken
|
37
|
+
* development: simple cucumber features for core functionality.
|
38
|
+
* upstream: depends on resque ~> 1.13
|
39
|
+
|
40
|
+
## 0.1.0 (2011-01-18)
|
41
|
+
|
42
|
+
* new feature: `resque-pool` command line interface
|
43
|
+
* this replaces need for a special startup script.
|
44
|
+
* manages PID file, logfiles, daemonizing, etc.
|
45
|
+
* `resque-pool --help` for more info and options
|
46
|
+
* updated example config, init.d script, including a chef recipe that should
|
47
|
+
work at EngineYard.
|
48
|
+
|
49
|
+
## 0.0.10 (2010-08-31)
|
50
|
+
|
51
|
+
* remove rubygems 1.3.6 dependency
|
52
|
+
|
53
|
+
## 0.0.9 (2010-08-26)
|
54
|
+
|
55
|
+
* new feature: `RESQUE_POOL_CONFIG` environment variable to set alt config file
|
56
|
+
* upgraded to resque 1.10, removing `Resque::Worker` monkeypatch
|
57
|
+
|
58
|
+
## 0.0.8 (2010-08-20)
|
59
|
+
|
60
|
+
* bugfix: using (or not using) environments in config file
|
61
|
+
|
62
|
+
## 0.0.7 (2010-08-16)
|
63
|
+
|
64
|
+
* new feature: split by environments in config file
|
65
|
+
* added example startup script, Rakefile, and monit config
|
66
|
+
|
67
|
+
## 0.0.5 (2010-06-29)
|
68
|
+
|
69
|
+
* bugfix: worker processes not shutting down after orphaned
|
70
|
+
|
71
|
+
## 0.0.4 (2010-06-29)
|
72
|
+
|
73
|
+
* first release used in production
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (C) 2010 by Nicholas Evans <nick@ekenosen.net>, et al.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
data/README.md
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
Resque Pool
|
2
|
+
===========
|
3
|
+
|
4
|
+
[![Build Status](https://secure.travis-ci.org/nevans/resque-pool.png)](http://travis-ci.org/nevans/resque-pool)
|
5
|
+
[![Dependency Status](https://gemnasium.com/nevans/resque-pool.png)](https://gemnasium.com/nevans/resque-pool)
|
6
|
+
|
7
|
+
Resque pool is a simple library for managing a pool of
|
8
|
+
[resque](http://github.com/defunkt/resque) workers. Given a a config file, it
|
9
|
+
manages your workers for you, starting up the appropriate number of workers for
|
10
|
+
each worker type.
|
11
|
+
|
12
|
+
Benefits
|
13
|
+
---------
|
14
|
+
|
15
|
+
* Less config - With a simple YAML file, you can start up a pool daemon, and it
|
16
|
+
will monitor your workers for you. An example init.d script, monit config,
|
17
|
+
and chef cookbook are provided.
|
18
|
+
* Less memory - If you are using Ruby Enterprise Edition, or any ruby with
|
19
|
+
copy-on-write safe garbage collection, this should save you a *lot* of memory
|
20
|
+
when you are managing many workers.
|
21
|
+
* Faster startup - when you start many workers at once, they would normally
|
22
|
+
compete for CPU as they load their environments. Resque-pool can load the
|
23
|
+
environment once and fork all of the workers almost instantly.
|
24
|
+
|
25
|
+
Upgrading?
|
26
|
+
-----------
|
27
|
+
|
28
|
+
See
|
29
|
+
[Changelog.md](https://github.com/nevans/resque-pool/blob/master/Changelog.md)
|
30
|
+
in case there are important or helpful changes.
|
31
|
+
|
32
|
+
How to use
|
33
|
+
-----------
|
34
|
+
|
35
|
+
### YAML file config
|
36
|
+
|
37
|
+
Create a `config/resque-pool.yml` (or `resque-pool.yml`) with your worker
|
38
|
+
counts. The YAML file supports both using root level defaults as well as
|
39
|
+
environment specific overrides (`RACK_ENV`, `RAILS_ENV`, and `RESQUE_ENV`
|
40
|
+
environment variables can be used to determine environment). For example in
|
41
|
+
`config/resque-pool.yml`:
|
42
|
+
|
43
|
+
foo: 1
|
44
|
+
bar: 2
|
45
|
+
"foo,bar,baz": 1
|
46
|
+
|
47
|
+
production:
|
48
|
+
"foo,bar,baz": 4
|
49
|
+
|
50
|
+
### Rake task config
|
51
|
+
|
52
|
+
Require the rake tasks (`resque/pool/tasks`) in your `Rakefile`, load your
|
53
|
+
application environment, configure Resque as necessary, and configure
|
54
|
+
`resque:pool:setup` to disconnect all open files and sockets in the pool
|
55
|
+
manager and reconnect in the workers. For example, with rails you should put
|
56
|
+
the following into `lib/tasks/resque.rake`:
|
57
|
+
|
58
|
+
require 'resque/pool/tasks'
|
59
|
+
# this task will get called before resque:pool:setup
|
60
|
+
# and preload the rails environment in the pool manager
|
61
|
+
task "resque:setup" => :environment do
|
62
|
+
# generic worker setup, e.g. Hoptoad for failed jobs
|
63
|
+
end
|
64
|
+
task "resque:pool:setup" do
|
65
|
+
# close any sockets or files in pool manager
|
66
|
+
ActiveRecord::Base.connection.disconnect!
|
67
|
+
# and re-open them in the resque worker parent
|
68
|
+
Resque::Pool.after_prefork do |job|
|
69
|
+
ActiveRecord::Base.establish_connection
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
### Start the pool manager
|
74
|
+
|
75
|
+
Then you can start the queues via:
|
76
|
+
|
77
|
+
resque-pool --daemon --environment production
|
78
|
+
|
79
|
+
This will start up seven worker processes, one exclusively for the foo queue,
|
80
|
+
two exclusively for the bar queue, and four workers looking at all queues in
|
81
|
+
priority. With the config above, this is similar to if you ran the following:
|
82
|
+
|
83
|
+
rake resque:work RAILS_ENV=production QUEUES=foo &
|
84
|
+
rake resque:work RAILS_ENV=production QUEUES=bar &
|
85
|
+
rake resque:work RAILS_ENV=production QUEUES=bar &
|
86
|
+
rake resque:work RAILS_ENV=production QUEUES=foo,bar,baz &
|
87
|
+
rake resque:work RAILS_ENV=production QUEUES=foo,bar,baz &
|
88
|
+
rake resque:work RAILS_ENV=production QUEUES=foo,bar,baz &
|
89
|
+
rake resque:work RAILS_ENV=production QUEUES=foo,bar,baz &
|
90
|
+
|
91
|
+
The pool manager will stay around monitoring the resque worker parents, giving
|
92
|
+
three levels: a single pool manager, many worker parents, and one worker child
|
93
|
+
per worker (when the actual job is being processed). For example, `ps -ef f |
|
94
|
+
grep [r]esque` (in Linux) might return something like the following:
|
95
|
+
|
96
|
+
resque 13858 1 0 13:44 ? S 0:02 resque-pool-manager: managing [13867, 13875, 13871, 13872, 13868, 13870, 13876]
|
97
|
+
resque 13867 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Waiting for foo
|
98
|
+
resque 13868 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Waiting for bar
|
99
|
+
resque 13870 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Waiting for bar
|
100
|
+
resque 13871 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Waiting for foo,bar,baz
|
101
|
+
resque 13872 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Forked 7481 at 1280343254
|
102
|
+
resque 7481 13872 0 14:54 ? S 0:00 \_ resque-1.9.9: Processing foo since 1280343254
|
103
|
+
resque 13875 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Waiting for foo,bar,baz
|
104
|
+
resque 13876 13858 0 13:44 ? S 0:00 \_ resque-1.9.9: Forked 7485 at 1280343255
|
105
|
+
resque 7485 13876 0 14:54 ? S 0:00 \_ resque-1.9.9: Processing bar since 1280343254
|
106
|
+
|
107
|
+
Running as a daemon will default to placing the pidfile and logfiles in the
|
108
|
+
conventional rails locations, although you can configure that. See
|
109
|
+
`resque-pool --help` for more options.
|
110
|
+
|
111
|
+
SIGNALS
|
112
|
+
-------
|
113
|
+
|
114
|
+
The pool manager responds to the following signals:
|
115
|
+
|
116
|
+
* `HUP` - reload the config file, reload logfiles, restart all workers.
|
117
|
+
* `QUIT` - send `QUIT` to each worker parent and shutdown the manager after all workers are done.
|
118
|
+
* `INT` - send `QUIT` to each worker parent and immediately shutdown manager
|
119
|
+
* `TERM` - send `TERM` to each worker parent and immediately shutdown manager
|
120
|
+
* `WINCH` - send `QUIT` to each worker, but keep manager running (send `HUP` to reload config and restart workers)
|
121
|
+
* `USR1`/`USR2`/`CONT` - pass the signal on to all worker parents (see Resque docs).
|
122
|
+
|
123
|
+
Use `HUP` to help logrotate run smoothly and to change the number of workers
|
124
|
+
per worker type.
|
125
|
+
|
126
|
+
Other Features
|
127
|
+
--------------
|
128
|
+
|
129
|
+
An example chef cookbook is provided (and should Just Work at Engine Yard as
|
130
|
+
is; just provide a `/data/#{app_name}/shared/config/resque-pool.yml` on your
|
131
|
+
utility instances). Even if you don't use chef you can use the example init.d
|
132
|
+
and monitrc erb templates in `examples/chef_cookbook/templates/default`.
|
133
|
+
|
134
|
+
You can also start a pool manager via `rake resque:pool` or from a plain old
|
135
|
+
ruby script by calling `Resque::Pool.run`.
|
136
|
+
|
137
|
+
Workers will watch the pool manager, and gracefully shutdown (after completing
|
138
|
+
their current job) if the manager process disappears before them.
|
139
|
+
|
140
|
+
You can specify an alternate config file by setting the `RESQUE_POOL_CONFIG` or
|
141
|
+
with the `--config` command line option.
|
142
|
+
|
143
|
+
TODO
|
144
|
+
-----
|
145
|
+
|
146
|
+
See [the TODO list](https://github.com/nevans/resque-pool/issues) at github issues.
|
147
|
+
|
148
|
+
Contributors
|
149
|
+
-------------
|
150
|
+
|
151
|
+
* John Schult (config file can be split by environment)
|
152
|
+
* Stephen Celis (increased gemspec sanity)
|
153
|
+
* Vincent Agnello, Robert Kamunyori, Paul Kauders; for pairing with me at
|
154
|
+
B'more on Rails Open Source Hack Nights. :)
|
155
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
# for loading the example config file in config/resque-pool.yml
|
5
|
+
require 'resque/pool/tasks'
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
9
|
+
t.rspec_opts = ["-c", "-f progress"]
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'cucumber/rake/task'
|
13
|
+
Cucumber::Rake::Task.new(:features) do |c|
|
14
|
+
c.profile = "rake"
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => [:spec, :features]
|
18
|
+
|
19
|
+
rule(/\.[1-9]$/ => [proc { |tn| "#{tn}.ronn" }]) do |t|
|
20
|
+
name = Resque::Pool.name.sub('::','-').upcase
|
21
|
+
version = "%s %s" % [name, Resque::Pool::VERSION.upcase]
|
22
|
+
|
23
|
+
manual = '--manual "%s"' % name
|
24
|
+
organization = '--organization "%s"' % version
|
25
|
+
sh "ronn #{manual} #{organization} <#{t.source} >#{t.name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
file 'man/resque-pool.1'
|
29
|
+
file 'man/resque-pool.yml.5'
|
30
|
+
task :manpages => ['man/resque-pool.1','man/resque-pool.yml.5']
|
data/bin/resque-pool
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
Feature: Basic resque-pool daemon configuration and operation
|
2
|
+
To easily manage a pool of resque workers, resque-pool provides a daemon with
|
3
|
+
simple configuration. Static configuration is handled in the
|
4
|
+
config/config.yml file and dynamic configuration is handled in the Rakefile.
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "Rakefile" with:
|
8
|
+
"""
|
9
|
+
require 'resque/pool/tasks'
|
10
|
+
"""
|
11
|
+
|
12
|
+
Scenario: no config file
|
13
|
+
When I run the pool manager as "resque-pool"
|
14
|
+
Then the pool manager should report that it has started up
|
15
|
+
And the pool manager should report that the pool is empty
|
16
|
+
And the pool manager should have no child processes
|
17
|
+
When I send the pool manager the "QUIT" signal
|
18
|
+
Then the pool manager should finish
|
19
|
+
And the pool manager should report that it is finished
|
20
|
+
|
21
|
+
@slow_exit
|
22
|
+
Scenario: basic config file
|
23
|
+
Given a file named "config/resque-pool.yml" with:
|
24
|
+
"""
|
25
|
+
foo: 1
|
26
|
+
bar: 2
|
27
|
+
"bar,baz": 3
|
28
|
+
"""
|
29
|
+
When I run the pool manager as "resque-pool"
|
30
|
+
Then the pool manager should report that it has started up
|
31
|
+
And the pool manager should report that 6 workers are in the pool
|
32
|
+
And the pool manager should have 1 "foo" worker child processes
|
33
|
+
And the pool manager should have 2 "bar" worker child processes
|
34
|
+
And the pool manager should have 3 "bar,baz" worker child processes
|
35
|
+
When I send the pool manager the "QUIT" signal
|
36
|
+
Then the resque workers should all shutdown
|
37
|
+
And the pool manager should finish
|
38
|
+
And the pool manager should report that a "foo" worker has been reaped
|
39
|
+
And the pool manager should report that a "bar" worker has been reaped
|
40
|
+
And the pool manager should report that a "bar,baz" worker has been reaped
|
41
|
+
And the pool manager should report that it is finished
|
42
|
+
|
43
|
+
Scenario: daemonized
|
44
|
+
Given a directory named "log"
|
45
|
+
And a directory named "tmp/pids"
|
46
|
+
And a file named "config/resque-pool.yml" with:
|
47
|
+
"""
|
48
|
+
foo: 2
|
49
|
+
bar: 4
|
50
|
+
"baz,quux": 4
|
51
|
+
"""
|
52
|
+
When I run the pool manager as "resque-pool -d"
|
53
|
+
Then the pool manager should record its pid in "tmp/pids/resque-pool.pid"
|
54
|
+
And the pool manager should daemonize
|
55
|
+
And a file named "log/resque-pool.stdout.log" should exist
|
56
|
+
And a file named "log/resque-pool.stderr.log" should exist
|
57
|
+
And the pool manager should log that it has started up
|
58
|
+
And the pool manager should log that 10 workers are in the pool
|
59
|
+
And the pool manager should have 2 "foo" worker child processes
|
60
|
+
And the pool manager should have 4 "bar" worker child processes
|
61
|
+
And the pool manager should have 4 "baz,quux" worker child processes
|
62
|
+
When I send the pool manager the "QUIT" signal
|
63
|
+
Then the resque workers should all shutdown
|
64
|
+
And the pool manager daemon should finish
|
65
|
+
And the pool manager should log that a "foo" worker has been reaped
|
66
|
+
And the pool manager should log that a "bar" worker has been reaped
|
67
|
+
And the pool manager should log that a "baz,quux" worker has been reaped
|
68
|
+
And the pool manager should log that it is finished
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# syntactic sugar, and separate ivar. daemons aren't interactive
|
2
|
+
When /^I run "([^"]*)" in the background$/ do |cmd|
|
3
|
+
run_background(unescape(cmd))
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the (output|logfiles) should contain the following lines \(with interpolated \$PID\):$/ do |output_logfiles, partial_output|
|
7
|
+
interpolate_background_pid(partial_output).split("\n").each do |line|
|
8
|
+
output_or_log(output_logfiles).should include(line)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
When /^I send "([^"]*)" the "([^"]*)" signal$/ do |cmd, signal|
|
13
|
+
send_signal(cmd, signal)
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the "([^"]*)" process should finish$/ do |cmd|
|
17
|
+
# doesn't actually stop... just polls for exit
|
18
|
+
processes[cmd].stop
|
19
|
+
end
|
20
|
+
|
21
|
+
Before("@slow_exit") do
|
22
|
+
@aruba_timeout_seconds = 10
|
23
|
+
end
|
24
|
+
|
25
|
+
After do
|
26
|
+
kill_all_processes!
|
27
|
+
# now kill the daemon!
|
28
|
+
begin
|
29
|
+
Process.kill(9, @pid_from_pidfile) if @pid_from_pidfile
|
30
|
+
rescue Errno::ESRCH
|
31
|
+
end
|
32
|
+
#`pkill -9 resque-pool`
|
33
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
def process_should_exist(pid)
|
2
|
+
lambda { Process.kill(0, pid) }.should_not raise_error(Errno::ESRCH)
|
3
|
+
end
|
4
|
+
|
5
|
+
def process_should_not_exist(pid)
|
6
|
+
lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH)
|
7
|
+
end
|
8
|
+
|
9
|
+
def grab_worker_pids(count, str)
|
10
|
+
puts "TODO: check output_or_log for #{count} worker started messages"
|
11
|
+
pid_regex = (1..count).map { '(\d+)' }.join ', '
|
12
|
+
full_regex = /resque-pool-manager\[aruba\]\[\d+\]: Pool contains worker PIDs: \[#{pid_regex}\]/m
|
13
|
+
str.should =~ full_regex
|
14
|
+
@worker_pids = full_regex.match(str).captures.map {|pid| pid.to_i }
|
15
|
+
end
|
16
|
+
|
17
|
+
def output_or_logfiles_string(report_log)
|
18
|
+
case report_log
|
19
|
+
when "report", "output"
|
20
|
+
"output"
|
21
|
+
when "log", "logfiles"
|
22
|
+
"logfiles"
|
23
|
+
else
|
24
|
+
raise ArgumentError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def output_or_log(report_log)
|
29
|
+
case report_log
|
30
|
+
when "report", "output"
|
31
|
+
interactive_output
|
32
|
+
when "log", "logfiles"
|
33
|
+
in_current_dir do
|
34
|
+
File.read("log/resque-pool.stdout.log") << File.read("log/resque-pool.stderr.log")
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise ArgumentError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class NotFinishedStarting < StandardError; end
|
42
|
+
def worker_processes_for(queues)
|
43
|
+
children_of(background_pid).select do |pid, cmd|
|
44
|
+
raise NotFinishedStarting if cmd =~ /Starting$/
|
45
|
+
cmd =~ /^resque-\d+.\d+.\d+: Waiting for #{queues}$/
|
46
|
+
end
|
47
|
+
rescue NotFinishedStarting
|
48
|
+
retry
|
49
|
+
end
|
50
|
+
|
51
|
+
def children_of(ppid)
|
52
|
+
ps = `ps -eo ppid,pid,cmd | grep '^ *#{ppid} '`
|
53
|
+
ps.split(/\s*\n/).map do |line|
|
54
|
+
_, pid, cmd = line.strip.split(/\s+/, 3)
|
55
|
+
[pid, cmd]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
When /^I run the pool manager as "([^"]*)"$/ do |cmd|
|
60
|
+
@pool_manager_process = run_background(unescape(cmd))
|
61
|
+
end
|
62
|
+
|
63
|
+
When /^I send the pool manager the "([^"]*)" signal$/ do |signal|
|
64
|
+
Process.kill signal, background_pid
|
65
|
+
output_logfiles = @pid_from_pidfile ? "logfiles" : "output"
|
66
|
+
case signal
|
67
|
+
when "QUIT"
|
68
|
+
keep_trying do
|
69
|
+
step "the #{output_logfiles} should contain the following lines (with interpolated $PID):", <<-EOF
|
70
|
+
resque-pool-manager[aruba][$PID]: QUIT: graceful shutdown, waiting for children
|
71
|
+
EOF
|
72
|
+
end
|
73
|
+
else
|
74
|
+
raise ArgumentError
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Then /^the pool manager should record its pid in "([^"]*)"$/ do |pidfile|
|
79
|
+
in_current_dir do
|
80
|
+
keep_trying do
|
81
|
+
File.should be_file(pidfile)
|
82
|
+
@pid_from_pidfile = File.read(pidfile).to_i
|
83
|
+
@pid_from_pidfile.should_not == 0
|
84
|
+
process_should_exist(@pid_from_pidfile)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Then /^the pool manager should daemonize$/ do
|
90
|
+
stop_processes!
|
91
|
+
end
|
92
|
+
|
93
|
+
Then /^the pool manager daemon should finish$/ do
|
94
|
+
keep_trying do
|
95
|
+
process_should_not_exist(@pid_from_pidfile)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# nomenclature: "report" => output to stdout/stderr
|
100
|
+
# "log" => output to default logfile
|
101
|
+
|
102
|
+
Then /^the pool manager should (report|log) that it has started up$/ do |report_log|
|
103
|
+
keep_trying do
|
104
|
+
step "the #{output_or_logfiles_string(report_log)} should contain the following lines (with interpolated $PID):", <<-EOF
|
105
|
+
resque-pool-manager[aruba][$PID]: Resque Pool running in test environment
|
106
|
+
resque-pool-manager[aruba][$PID]: started manager
|
107
|
+
EOF
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
Then /^the pool manager should (report|log) that the pool is empty$/ do |report_log|
|
112
|
+
step "the #{output_or_logfiles_string(report_log)} should contain the following lines (with interpolated $PID):", <<-EOF
|
113
|
+
resque-pool-manager[aruba][$PID]: Pool is empty
|
114
|
+
EOF
|
115
|
+
end
|
116
|
+
|
117
|
+
Then /^the pool manager should (report|log) that (\d+) workers are in the pool$/ do |report_log, count|
|
118
|
+
grab_worker_pids Integer(count), output_or_log(report_log)
|
119
|
+
end
|
120
|
+
|
121
|
+
Then /^the resque workers should all shutdown$/ do
|
122
|
+
@worker_pids.each do |pid|
|
123
|
+
keep_trying do
|
124
|
+
process_should_not_exist(pid)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
Then "the pool manager should have no child processes" do
|
130
|
+
children_of(background_pid).should have(:no).keys
|
131
|
+
end
|
132
|
+
|
133
|
+
Then /^the pool manager should have (\d+) "([^"]*)" worker child processes$/ do |count, queues|
|
134
|
+
worker_processes_for(queues).should have(Integer(count)).members
|
135
|
+
end
|
136
|
+
|
137
|
+
Then "the pool manager should finish" do
|
138
|
+
# assuming there will not be multiple processes running
|
139
|
+
stop_processes!
|
140
|
+
end
|
141
|
+
|
142
|
+
Then /^the pool manager should (report|log) that it is finished$/ do |report_log|
|
143
|
+
step "the #{output_or_logfiles_string(report_log)} should contain the following lines (with interpolated $PID):", <<-EOF
|
144
|
+
resque-pool-manager[aruba][$PID]: manager finished
|
145
|
+
EOF
|
146
|
+
end
|
147
|
+
|
148
|
+
Then /^the pool manager should (report|log) that a "([^"]*)" worker has been reaped$/ do |report_log, worker_type|
|
149
|
+
step 'the '+ output_or_logfiles_string(report_log) +' should match /Reaped resque worker\[\d+\] \(status: 0\) queues: '+ worker_type + '/'
|
150
|
+
end
|
151
|
+
|
152
|
+
Then /^the logfiles should match \/([^\/]*)\/$/ do |partial_output|
|
153
|
+
output_or_log("log").should =~ /#{partial_output}/
|
154
|
+
end
|
155
|
+
|