opengotham_resque 1.8.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.
- data/.gitignore +2 -0
- data/.kick +26 -0
- data/HISTORY.md +142 -0
- data/LICENSE +20 -0
- data/README.markdown +794 -0
- data/Rakefile +112 -0
- data/bin/resque +57 -0
- data/bin/resque-web +23 -0
- data/config.ru +14 -0
- data/deps.rip +7 -0
- data/docs/HOOKS.md +121 -0
- data/docs/PLUGINS.md +93 -0
- data/examples/async_helper.rb +31 -0
- data/examples/demo/README.markdown +71 -0
- data/examples/demo/Rakefile +8 -0
- data/examples/demo/app.rb +38 -0
- data/examples/demo/config.ru +19 -0
- data/examples/demo/job.rb +22 -0
- data/examples/god/resque.god +53 -0
- data/examples/god/stale.god +26 -0
- data/examples/instance.rb +11 -0
- data/examples/monit/resque.monit +6 -0
- data/examples/simple.rb +30 -0
- data/init.rb +1 -0
- data/lib/resque.rb +287 -0
- data/lib/resque/errors.rb +10 -0
- data/lib/resque/failure.rb +66 -0
- data/lib/resque/failure/base.rb +61 -0
- data/lib/resque/failure/hoptoad.rb +132 -0
- data/lib/resque/failure/multiple.rb +48 -0
- data/lib/resque/failure/redis.rb +40 -0
- data/lib/resque/helpers.rb +63 -0
- data/lib/resque/job.rb +207 -0
- data/lib/resque/plugin.rb +46 -0
- data/lib/resque/server.rb +201 -0
- data/lib/resque/server/public/idle.png +0 -0
- data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
- data/lib/resque/server/public/jquery.relatize_date.js +95 -0
- data/lib/resque/server/public/poll.png +0 -0
- data/lib/resque/server/public/ranger.js +67 -0
- data/lib/resque/server/public/reset.css +48 -0
- data/lib/resque/server/public/style.css +81 -0
- data/lib/resque/server/public/working.png +0 -0
- data/lib/resque/server/test_helper.rb +19 -0
- data/lib/resque/server/views/error.erb +1 -0
- data/lib/resque/server/views/failed.erb +53 -0
- data/lib/resque/server/views/key_sets.erb +20 -0
- data/lib/resque/server/views/key_string.erb +11 -0
- data/lib/resque/server/views/layout.erb +44 -0
- data/lib/resque/server/views/next_more.erb +10 -0
- data/lib/resque/server/views/overview.erb +4 -0
- data/lib/resque/server/views/queues.erb +49 -0
- data/lib/resque/server/views/stats.erb +62 -0
- data/lib/resque/server/views/workers.erb +78 -0
- data/lib/resque/server/views/working.erb +69 -0
- data/lib/resque/stat.rb +53 -0
- data/lib/resque/tasks.rb +39 -0
- data/lib/resque/version.rb +3 -0
- data/lib/resque/worker.rb +478 -0
- data/tasks/redis.rake +159 -0
- data/tasks/resque.rake +2 -0
- data/test/job_hooks_test.rb +302 -0
- data/test/job_plugins_test.rb +209 -0
- data/test/plugin_test.rb +116 -0
- data/test/redis-test.conf +132 -0
- data/test/resque-web_test.rb +54 -0
- data/test/resque_test.rb +225 -0
- data/test/test_helper.rb +111 -0
- data/test/worker_test.rb +302 -0
- metadata +199 -0
data/tasks/redis.rake
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
# Inspired by rabbitmq.rake the Redbox project at http://github.com/rick/redbox/tree/master
|
2
|
+
require 'fileutils'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class RedisRunner
|
7
|
+
|
8
|
+
def self.redis_dir
|
9
|
+
@redis_dir ||= if ENV['PREFIX']
|
10
|
+
Pathname.new(ENV['PREFIX'])
|
11
|
+
else
|
12
|
+
Pathname.new(`which redis-server`) + '..' + '..'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.bin_dir
|
17
|
+
redis_dir + 'bin'
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.config
|
21
|
+
@config ||= if File.exists?(redis_dir + 'etc/redis.conf')
|
22
|
+
redis_dir + 'etc/redis.conf'
|
23
|
+
else
|
24
|
+
redis_dir + '../etc/redis.conf'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.dtach_socket
|
29
|
+
'/tmp/redis.dtach'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Just check for existance of dtach socket
|
33
|
+
def self.running?
|
34
|
+
File.exists? dtach_socket
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.start
|
38
|
+
puts 'Detach with Ctrl+\ Re-attach with rake redis:attach'
|
39
|
+
sleep 1
|
40
|
+
command = "#{bin_dir}/dtach -A #{dtach_socket} #{bin_dir}/redis-server #{config}"
|
41
|
+
sh command
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.attach
|
45
|
+
exec "#{bin_dir}/dtach -a #{dtach_socket}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.stop
|
49
|
+
sh 'echo "SHUTDOWN" | nc localhost 6379'
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
namespace :redis do
|
55
|
+
|
56
|
+
desc 'About redis'
|
57
|
+
task :about do
|
58
|
+
puts "\nSee http://code.google.com/p/redis/ for information about redis.\n\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
desc 'Start redis'
|
62
|
+
task :start do
|
63
|
+
RedisRunner.start
|
64
|
+
end
|
65
|
+
|
66
|
+
desc 'Stop redis'
|
67
|
+
task :stop do
|
68
|
+
RedisRunner.stop
|
69
|
+
end
|
70
|
+
|
71
|
+
desc 'Restart redis'
|
72
|
+
task :restart do
|
73
|
+
RedisRunner.stop
|
74
|
+
RedisRunner.start
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Attach to redis dtach socket'
|
78
|
+
task :attach do
|
79
|
+
RedisRunner.attach
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'Install the latest verison of Redis from Github (requires git, duh)'
|
83
|
+
task :install => [:about, :download, :make] do
|
84
|
+
bin_dir = '/usr/bin'
|
85
|
+
conf_dir = '/etc'
|
86
|
+
|
87
|
+
if ENV['PREFIX']
|
88
|
+
bin_dir = "#{ENV['PREFIX']}/bin"
|
89
|
+
sh "mkdir -p #{bin_dir}" unless File.exists?("#{bin_dir}")
|
90
|
+
|
91
|
+
conf_dir = "#{ENV['PREFIX']}/etc"
|
92
|
+
sh "mkdir -p #{conf_dir}" unless File.exists?("#{conf_dir}")
|
93
|
+
end
|
94
|
+
|
95
|
+
%w(redis-benchmark redis-cli redis-server).each do |bin|
|
96
|
+
sh "cp /tmp/redis/#{bin} #{bin_dir}"
|
97
|
+
end
|
98
|
+
|
99
|
+
puts "Installed redis-benchmark, redis-cli and redis-server to #{bin_dir}"
|
100
|
+
|
101
|
+
unless File.exists?("#{conf_dir}/redis.conf")
|
102
|
+
sh "cp /tmp/redis/redis.conf #{conf_dir}/redis.conf"
|
103
|
+
puts "Installed redis.conf to #{conf_dir} \n You should look at this file!"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
task :make do
|
108
|
+
sh "cd /tmp/redis && make clean"
|
109
|
+
sh "cd /tmp/redis && make"
|
110
|
+
end
|
111
|
+
|
112
|
+
desc "Download package"
|
113
|
+
task :download do
|
114
|
+
sh 'rm -rf /tmp/redis/' if File.exists?("/tmp/redis/.svn")
|
115
|
+
sh 'git clone git://github.com/antirez/redis.git /tmp/redis' unless File.exists?('/tmp/redis')
|
116
|
+
sh "cd /tmp/redis && git pull" if File.exists?("/tmp/redis/.git")
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
namespace :dtach do
|
122
|
+
|
123
|
+
desc 'About dtach'
|
124
|
+
task :about do
|
125
|
+
puts "\nSee http://dtach.sourceforge.net/ for information about dtach.\n\n"
|
126
|
+
end
|
127
|
+
|
128
|
+
desc 'Install dtach 0.8 from source'
|
129
|
+
task :install => [:about, :download, :make] do
|
130
|
+
|
131
|
+
bin_dir = "/usr/bin"
|
132
|
+
|
133
|
+
if ENV['PREFIX']
|
134
|
+
bin_dir = "#{ENV['PREFIX']}/bin"
|
135
|
+
sh "mkdir -p #{bin_dir}" unless File.exists?("#{bin_dir}")
|
136
|
+
end
|
137
|
+
|
138
|
+
sh "cp /tmp/dtach-0.8/dtach #{bin_dir}"
|
139
|
+
end
|
140
|
+
|
141
|
+
task :make do
|
142
|
+
sh 'cd /tmp/dtach-0.8/ && ./configure && make'
|
143
|
+
end
|
144
|
+
|
145
|
+
desc "Download package"
|
146
|
+
task :download do
|
147
|
+
unless File.exists?('/tmp/dtach-0.8.tar.gz')
|
148
|
+
require 'net/http'
|
149
|
+
|
150
|
+
url = 'http://downloads.sourceforge.net/project/dtach/dtach/0.8/dtach-0.8.tar.gz'
|
151
|
+
open('/tmp/dtach-0.8.tar.gz', 'wb') do |file| file.write(open(url).read) end
|
152
|
+
end
|
153
|
+
|
154
|
+
unless File.directory?('/tmp/dtach-0.8')
|
155
|
+
sh 'cd /tmp && tar xzf dtach-0.8.tar.gz'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
data/tasks/resque.rake
ADDED
@@ -0,0 +1,302 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
context "Resque::Job before_perform" do
|
4
|
+
include PerformJob
|
5
|
+
|
6
|
+
class BeforePerformJob
|
7
|
+
def self.before_perform_record_history(history)
|
8
|
+
history << :before_perform
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.perform(history)
|
12
|
+
history << :perform
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test "it runs before_perform before perform" do
|
17
|
+
result = perform_job(BeforePerformJob, history=[])
|
18
|
+
assert_equal true, result, "perform returned true"
|
19
|
+
assert_equal history, [:before_perform, :perform]
|
20
|
+
end
|
21
|
+
|
22
|
+
class BeforePerformJobFails
|
23
|
+
def self.before_perform_fail_job(history)
|
24
|
+
history << :before_perform
|
25
|
+
raise StandardError
|
26
|
+
end
|
27
|
+
def self.perform(history)
|
28
|
+
history << :perform
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
test "raises an error and does not perform if before_perform fails" do
|
33
|
+
history = []
|
34
|
+
assert_raises StandardError do
|
35
|
+
perform_job(BeforePerformJobFails, history)
|
36
|
+
end
|
37
|
+
assert_equal history, [:before_perform], "Only before_perform was run"
|
38
|
+
end
|
39
|
+
|
40
|
+
class BeforePerformJobAborts
|
41
|
+
def self.before_perform_abort(history)
|
42
|
+
history << :before_perform
|
43
|
+
raise Resque::Job::DontPerform
|
44
|
+
end
|
45
|
+
def self.perform(history)
|
46
|
+
history << :perform
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
test "does not perform if before_perform raises Resque::Job::DontPerform" do
|
51
|
+
result = perform_job(BeforePerformJobAborts, history=[])
|
52
|
+
assert_equal false, result, "perform returned false"
|
53
|
+
assert_equal history, [:before_perform], "Only before_perform was run"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "Resque::Job after_perform" do
|
58
|
+
include PerformJob
|
59
|
+
|
60
|
+
class AfterPerformJob
|
61
|
+
def self.perform(history)
|
62
|
+
history << :perform
|
63
|
+
end
|
64
|
+
def self.after_perform_record_history(history)
|
65
|
+
history << :after_perform
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
test "it runs after_perform after perform" do
|
70
|
+
result = perform_job(AfterPerformJob, history=[])
|
71
|
+
assert_equal true, result, "perform returned true"
|
72
|
+
assert_equal history, [:perform, :after_perform]
|
73
|
+
end
|
74
|
+
|
75
|
+
class AfterPerformJobFails
|
76
|
+
def self.perform(history)
|
77
|
+
history << :perform
|
78
|
+
end
|
79
|
+
def self.after_perform_fail_job(history)
|
80
|
+
history << :after_perform
|
81
|
+
raise StandardError
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
test "raises an error but has already performed if after_perform fails" do
|
86
|
+
history = []
|
87
|
+
assert_raises StandardError do
|
88
|
+
perform_job(AfterPerformJobFails, history)
|
89
|
+
end
|
90
|
+
assert_equal history, [:perform, :after_perform], "Only after_perform was run"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "Resque::Job around_perform" do
|
95
|
+
include PerformJob
|
96
|
+
|
97
|
+
class AroundPerformJob
|
98
|
+
def self.perform(history)
|
99
|
+
history << :perform
|
100
|
+
end
|
101
|
+
def self.around_perform_record_history(history)
|
102
|
+
history << :start_around_perform
|
103
|
+
yield
|
104
|
+
history << :finish_around_perform
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
test "it runs around_perform then yields in order to perform" do
|
109
|
+
result = perform_job(AroundPerformJob, history=[])
|
110
|
+
assert_equal true, result, "perform returned true"
|
111
|
+
assert_equal history, [:start_around_perform, :perform, :finish_around_perform]
|
112
|
+
end
|
113
|
+
|
114
|
+
class AroundPerformJobFailsBeforePerforming
|
115
|
+
def self.perform(history)
|
116
|
+
history << :perform
|
117
|
+
end
|
118
|
+
def self.around_perform_fail(history)
|
119
|
+
history << :start_around_perform
|
120
|
+
raise StandardError
|
121
|
+
yield
|
122
|
+
history << :finish_around_perform
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
test "raises an error and does not perform if around_perform fails before yielding" do
|
127
|
+
history = []
|
128
|
+
assert_raises StandardError do
|
129
|
+
perform_job(AroundPerformJobFailsBeforePerforming, history)
|
130
|
+
end
|
131
|
+
assert_equal history, [:start_around_perform], "Only part of around_perform was run"
|
132
|
+
end
|
133
|
+
|
134
|
+
class AroundPerformJobFailsWhilePerforming
|
135
|
+
def self.perform(history)
|
136
|
+
history << :perform
|
137
|
+
raise StandardError
|
138
|
+
end
|
139
|
+
def self.around_perform_fail_in_yield(history)
|
140
|
+
history << :start_around_perform
|
141
|
+
begin
|
142
|
+
yield
|
143
|
+
ensure
|
144
|
+
history << :ensure_around_perform
|
145
|
+
end
|
146
|
+
history << :finish_around_perform
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
test "raises an error but may handle exceptions if perform fails" do
|
151
|
+
history = []
|
152
|
+
assert_raises StandardError do
|
153
|
+
perform_job(AroundPerformJobFailsWhilePerforming, history)
|
154
|
+
end
|
155
|
+
assert_equal history, [:start_around_perform, :perform, :ensure_around_perform], "Only part of around_perform was run"
|
156
|
+
end
|
157
|
+
|
158
|
+
class AroundPerformJobDoesNotHaveToYield
|
159
|
+
def self.perform(history)
|
160
|
+
history << :perform
|
161
|
+
end
|
162
|
+
def self.around_perform_dont_yield(history)
|
163
|
+
history << :start_around_perform
|
164
|
+
history << :finish_around_perform
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
test "around_perform is not required to yield" do
|
169
|
+
history = []
|
170
|
+
result = perform_job(AroundPerformJobDoesNotHaveToYield, history)
|
171
|
+
assert_equal false, result, "perform returns false"
|
172
|
+
assert_equal history, [:start_around_perform, :finish_around_perform], "perform was not run"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "Resque::Job on_failure" do
|
177
|
+
include PerformJob
|
178
|
+
|
179
|
+
class FailureJobThatDoesNotFail
|
180
|
+
def self.perform(history)
|
181
|
+
history << :perform
|
182
|
+
end
|
183
|
+
def self.on_failure_record_failure(exception, history)
|
184
|
+
history << exception.message
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
test "it does not call on_failure if no failures occur" do
|
189
|
+
result = perform_job(FailureJobThatDoesNotFail, history=[])
|
190
|
+
assert_equal true, result, "perform returned true"
|
191
|
+
assert_equal history, [:perform]
|
192
|
+
end
|
193
|
+
|
194
|
+
class FailureJobThatFails
|
195
|
+
def self.perform(history)
|
196
|
+
history << :perform
|
197
|
+
raise StandardError, "oh no"
|
198
|
+
end
|
199
|
+
def self.on_failure_record_failure(exception, history)
|
200
|
+
history << exception.message
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
test "it calls on_failure with the exception and then re-raises the exception" do
|
205
|
+
history = []
|
206
|
+
assert_raises StandardError do
|
207
|
+
perform_job(FailureJobThatFails, history)
|
208
|
+
end
|
209
|
+
assert_equal history, [:perform, "oh no"]
|
210
|
+
end
|
211
|
+
|
212
|
+
class FailureJobThatFailsBadly
|
213
|
+
def self.perform(history)
|
214
|
+
history << :perform
|
215
|
+
raise SyntaxError, "oh no"
|
216
|
+
end
|
217
|
+
def self.on_failure_record_failure(exception, history)
|
218
|
+
history << exception.message
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
test "it calls on_failure even with bad exceptions" do
|
223
|
+
history = []
|
224
|
+
assert_raises SyntaxError do
|
225
|
+
perform_job(FailureJobThatFailsBadly, history)
|
226
|
+
end
|
227
|
+
assert_equal history, [:perform, "oh no"]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "Resque::Job all hooks" do
|
232
|
+
include PerformJob
|
233
|
+
|
234
|
+
class VeryHookyJob
|
235
|
+
def self.before_perform_record_history(history)
|
236
|
+
history << :before_perform
|
237
|
+
end
|
238
|
+
def self.around_perform_record_history(history)
|
239
|
+
history << :start_around_perform
|
240
|
+
yield
|
241
|
+
history << :finish_around_perform
|
242
|
+
end
|
243
|
+
def self.perform(history)
|
244
|
+
history << :perform
|
245
|
+
end
|
246
|
+
def self.after_perform_record_history(history)
|
247
|
+
history << :after_perform
|
248
|
+
end
|
249
|
+
def self.on_failure_record_history(exception, history)
|
250
|
+
history << exception.message
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
test "the complete hook order" do
|
255
|
+
result = perform_job(VeryHookyJob, history=[])
|
256
|
+
assert_equal true, result, "perform returned true"
|
257
|
+
assert_equal history, [
|
258
|
+
:before_perform,
|
259
|
+
:start_around_perform,
|
260
|
+
:perform,
|
261
|
+
:finish_around_perform,
|
262
|
+
:after_perform
|
263
|
+
]
|
264
|
+
end
|
265
|
+
|
266
|
+
class VeryHookyJobThatFails
|
267
|
+
def self.before_perform_record_history(history)
|
268
|
+
history << :before_perform
|
269
|
+
end
|
270
|
+
def self.around_perform_record_history(history)
|
271
|
+
history << :start_around_perform
|
272
|
+
yield
|
273
|
+
history << :finish_around_perform
|
274
|
+
end
|
275
|
+
def self.perform(history)
|
276
|
+
history << :perform
|
277
|
+
end
|
278
|
+
def self.after_perform_record_history(history)
|
279
|
+
history << :after_perform
|
280
|
+
raise StandardError, "oh no"
|
281
|
+
end
|
282
|
+
def self.on_failure_record_history(exception, history)
|
283
|
+
history << exception.message
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
test "the complete hook order with a failure at the last minute" do
|
288
|
+
history = []
|
289
|
+
assert_raises StandardError do
|
290
|
+
perform_job(VeryHookyJobThatFails, history)
|
291
|
+
end
|
292
|
+
assert_equal history, [
|
293
|
+
:before_perform,
|
294
|
+
:start_around_perform,
|
295
|
+
:perform,
|
296
|
+
:finish_around_perform,
|
297
|
+
:after_perform,
|
298
|
+
"oh no"
|
299
|
+
]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|