resque-pool-diet 0.3.1
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 +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
|
+
[](http://travis-ci.org/nevans/resque-pool)
|
5
|
+
[](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
|
+
|