powerhome-resque-status 0.6.0

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.
@@ -0,0 +1,358 @@
1
+ require 'test_helper'
2
+
3
+ class TestResquePluginsStatus < Minitest::Test
4
+
5
+ describe "Resque::Plugins::Status" do
6
+ before do
7
+ Resque.redis.flushall
8
+ end
9
+
10
+ describe ".create" do
11
+ describe "not inline" do
12
+ before do
13
+ @uuid = WorkingJob.create('num' => 100)
14
+ end
15
+
16
+ it "add the job to the queue" do
17
+ assert_equal 1, Resque.size(:statused)
18
+ end
19
+
20
+ it "set the queued object to the current class" do
21
+ job = Resque.pop(:statused)
22
+ assert_equal @uuid, job['args'].first
23
+ assert_equal "WorkingJob", job['class']
24
+ end
25
+
26
+ it "add the uuid to the statuses" do
27
+ assert_includes Resque::Plugins::Status::Hash.status_ids, @uuid
28
+ end
29
+
30
+ it "return a UUID" do
31
+ assert_match(/^\w{32}$/, @uuid)
32
+ end
33
+ end
34
+
35
+ describe "inline" do
36
+ before do
37
+ Resque.stubs(:inline?).returns(true)
38
+ end
39
+
40
+ it "not queue a job" do
41
+ @uuid = WorkingJob.create('num' => 100)
42
+ assert_equal 0, Resque.size(:statused)
43
+ end
44
+
45
+ it "call perform" do
46
+ WorkingJob.any_instance.expects(:perform).once
47
+ @uuid = WorkingJob.create('num' => 100)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe ".create with a failing before_enqueue hook" do
53
+ before do
54
+ @size = Resque.size(:statused)
55
+ @status_ids_size = Resque::Plugins::Status::Hash.status_ids.length
56
+ @res = NeverQueuedJob.create(:num => 100)
57
+ end
58
+
59
+ it "return nil" do
60
+ assert_equal nil, @res
61
+ end
62
+
63
+ it "not create a status" do
64
+ assert_equal @size, Resque.size(:statused)
65
+ end
66
+
67
+ it "not add the uuid to the statuses" do
68
+ assert_equal @status_ids_size, Resque::Plugins::Status::Hash.status_ids.length
69
+ end
70
+ end
71
+
72
+ describe ".scheduled" do
73
+ before do
74
+ @job_args = {'num' => 100}
75
+ @uuid = WorkingJob.scheduled(:queue_name, WorkingJob, @job_args)
76
+ end
77
+
78
+ it "create the job with the provided arguments" do
79
+ job = Resque.pop(:queue_name)
80
+ assert_equal @job_args, job['args'].last
81
+ end
82
+ end
83
+
84
+ describe ".enqueue" do
85
+ it "delegate to enqueue_to, filling in the queue from the class" do
86
+ @uuid = BasicJob.enqueue(WorkingJob, :num => 100)
87
+ @payload = Resque.pop(:statused)
88
+ assert_equal "WorkingJob", @payload['class']
89
+ end
90
+ end
91
+
92
+ describe ".enqueue_to" do
93
+ before do
94
+ @uuid = BasicJob.enqueue_to(:new_queue, WorkingJob, :num => 100)
95
+ @payload = Resque.pop(:new_queue)
96
+ end
97
+
98
+ it "add the job with the specific class to the queue" do
99
+ assert_equal "WorkingJob", @payload['class']
100
+ end
101
+
102
+ it "add the arguments to the options hash" do
103
+ assert_equal @uuid, @payload['args'].first
104
+ end
105
+
106
+ it "add the uuid to the statuses" do
107
+ assert_includes Resque::Plugins::Status::Hash.status_ids, @uuid
108
+ end
109
+
110
+ it "return UUID" do
111
+ assert_match(/^\w{32}$/, @uuid)
112
+ end
113
+
114
+ end
115
+
116
+ describe ".dequeue" do
117
+ before do
118
+ @uuid1 = BasicJob.enqueue(WorkingJob, :num => 100)
119
+ @uuid2 = BasicJob.enqueue(WorkingJob, :num => 100)
120
+ end
121
+
122
+ it "dequeue the job with the uuid from the correct queue" do
123
+ size = Resque.size(:statused)
124
+ BasicJob.dequeue(WorkingJob, @uuid2)
125
+ assert_equal size-1, Resque.size(:statused)
126
+ end
127
+ it "not dequeue any jobs with different uuids for same class name" do
128
+ BasicJob.dequeue(WorkingJob, @uuid2)
129
+ assert_equal @uuid1, Resque.pop(:statused)['args'].first
130
+ end
131
+ end
132
+
133
+ describe ".perform" do
134
+ let(:expectation) { }
135
+
136
+ before do
137
+ expectation
138
+ @uuid = WorkingJob.create(:num => 100)
139
+ @payload = Resque.pop(:statused)
140
+ @performed = WorkingJob.perform(*@payload['args'])
141
+ end
142
+
143
+ it "load load a new instance of the klass" do
144
+ assert @performed.is_a?(WorkingJob)
145
+ end
146
+
147
+ it "set the uuid" do
148
+ assert_equal @uuid, @performed.uuid
149
+ end
150
+
151
+ it "set the status" do
152
+ assert @performed.status.is_a?(Resque::Plugins::Status::Hash)
153
+ assert_equal 'WorkingJob({"num"=>100})', @performed.status.name
154
+ end
155
+
156
+ describe "before" do
157
+ let(:expectation) { WorkingJob.any_instance.expects(:perform).once }
158
+ it("call perform on the inherited class") {}
159
+ end
160
+ end
161
+
162
+ describe "manually failing a job" do
163
+ before do
164
+ @uuid = FailureJob.create(:num => 100)
165
+ @payload = Resque.pop(:statused)
166
+ @performed = FailureJob.perform(*@payload['args'])
167
+ end
168
+
169
+ it "load load a new instance of the klass" do
170
+ assert @performed.is_a?(FailureJob)
171
+ end
172
+
173
+ it "set the uuid" do
174
+ assert_equal @uuid, @performed.uuid
175
+ end
176
+
177
+ it "set the status" do
178
+ assert @performed.status.is_a?(Resque::Plugins::Status::Hash)
179
+ assert_equal 'FailureJob({"num"=>100})', @performed.status.name
180
+ end
181
+
182
+ it "be failed" do
183
+ assert_match(/failure/, @performed.status.message)
184
+ assert @performed.status.failed?
185
+ end
186
+
187
+ end
188
+
189
+ describe "killing a job" do
190
+ before do
191
+ @uuid = KillableJob.create(:num => 100)
192
+ @payload = Resque.pop(:statused)
193
+ Resque::Plugins::Status::Hash.kill(@uuid)
194
+ assert_includes Resque::Plugins::Status::Hash.kill_ids, @uuid
195
+ @performed = KillableJob.perform(*@payload['args'])
196
+ @status = Resque::Plugins::Status::Hash.get(@uuid)
197
+ end
198
+
199
+ it "set the status to killed" do
200
+ assert @status.killed?
201
+ assert !@status.completed?
202
+ end
203
+
204
+ it "only perform iterations up to kill" do
205
+ assert_equal 1, Resque.redis.get("#{@uuid}:iterations").to_i
206
+ end
207
+
208
+ it "not persist the kill key" do
209
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid
210
+ end
211
+ end
212
+
213
+ describe "killing all jobs" do
214
+ before do
215
+ @uuid1 = KillableJob.create(:num => 100)
216
+ @uuid2 = KillableJob.create(:num => 100)
217
+
218
+ Resque::Plugins::Status::Hash.killall
219
+
220
+ assert_includes Resque::Plugins::Status::Hash.kill_ids, @uuid1
221
+ assert_includes Resque::Plugins::Status::Hash.kill_ids, @uuid2
222
+
223
+ @payload1 = Resque.pop(:statused)
224
+ @payload2 = Resque.pop(:statused)
225
+
226
+ @performed = KillableJob.perform(*@payload1['args'])
227
+ @performed = KillableJob.perform(*@payload2['args'])
228
+
229
+ @status1, @status2 = Resque::Plugins::Status::Hash.mget([@uuid1, @uuid2])
230
+ end
231
+
232
+ it "set the status to killed" do
233
+ assert @status1.killed?
234
+ assert !@status1.completed?
235
+ assert @status2.killed?
236
+ assert !@status2.completed?
237
+ end
238
+
239
+ it "only perform iterations up to kill" do
240
+ assert_equal 1, Resque.redis.get("#{@uuid1}:iterations").to_i
241
+ assert_equal 1, Resque.redis.get("#{@uuid2}:iterations").to_i
242
+ end
243
+
244
+ it "not persist the kill key" do
245
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid1
246
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid2
247
+ end
248
+
249
+ end
250
+
251
+ describe "invoking killall jobs to kill a range" do
252
+ before do
253
+ @uuid1 = KillableJob.create(:num => 100)
254
+ @uuid2 = KillableJob.create(:num => 100)
255
+
256
+ Resque::Plugins::Status::Hash.killall(0,0) # only @uuid2 it be killed
257
+
258
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid1
259
+ assert_includes Resque::Plugins::Status::Hash.kill_ids, @uuid2
260
+
261
+ @payload1 = Resque.pop(:statused)
262
+ @payload2 = Resque.pop(:statused)
263
+
264
+ @performed = KillableJob.perform(*@payload1['args'])
265
+ @performed = KillableJob.perform(*@payload2['args'])
266
+
267
+ @status1, @status2 = Resque::Plugins::Status::Hash.mget([@uuid1, @uuid2])
268
+ end
269
+
270
+ it "set the status to killed" do
271
+ assert !@status1.killed?
272
+ assert @status1.completed?
273
+ assert @status2.killed?
274
+ assert !@status2.completed?
275
+ end
276
+
277
+ it "only perform iterations up to kill" do
278
+ assert_equal 100, Resque.redis.get("#{@uuid1}:iterations").to_i
279
+ assert_equal 1, Resque.redis.get("#{@uuid2}:iterations").to_i
280
+ end
281
+
282
+ it "not persist the kill key" do
283
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid1
284
+ refute_includes Resque::Plugins::Status::Hash.kill_ids, @uuid2
285
+ end
286
+
287
+ end
288
+
289
+ describe "with an invoked job" do
290
+ before do
291
+ @job = WorkingJob.new('123', {'num' => 100})
292
+ end
293
+
294
+ describe "#at" do
295
+ before do
296
+ @job.at(50, 100, "At 50%")
297
+ end
298
+
299
+ it "calculate percent" do
300
+ assert_equal 50, @job.status.pct_complete
301
+ end
302
+
303
+ it "set status" do
304
+ assert @job.status.working?
305
+ end
306
+
307
+ it "save message" do
308
+ assert_equal "At 50%", @job.status.message
309
+ end
310
+ end
311
+
312
+ describe "#failed" do
313
+ before do
314
+ @job.failed("OOOOPS!")
315
+ end
316
+
317
+ it "set status" do
318
+ assert @job.status.failed?
319
+ end
320
+
321
+ it "set message" do
322
+ assert_equal "OOOOPS!", @job.status.message
323
+ end
324
+ end
325
+
326
+ describe "#completed" do
327
+ before do
328
+ @job.completed
329
+ end
330
+
331
+ it "set status" do
332
+ assert @job.status.completed?
333
+ end
334
+
335
+ it "set message" do
336
+ assert_match(/complete/i, @job.status.message)
337
+ end
338
+
339
+ end
340
+
341
+ describe "#safe_perform!" do
342
+ before do
343
+ @job = ErrorJob.new("123")
344
+ assert_raises(RuntimeError) do
345
+ @job.safe_perform!
346
+ end
347
+ end
348
+
349
+ it "set status as failed" do
350
+ assert @job.status.failed?
351
+ end
352
+ end
353
+
354
+ end
355
+
356
+ end
357
+
358
+ end
@@ -0,0 +1,222 @@
1
+ require 'test_helper'
2
+
3
+ class TestResquePluginsStatusHash < Minitest::Test
4
+
5
+ describe "Resque::Plugins::Status::Hash" do
6
+ before do
7
+ Resque.redis.flushall
8
+ Resque::Plugins::Status::Hash.expire_in = nil
9
+ @uuid = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
10
+ Resque::Plugins::Status::Hash.set(@uuid, "my status")
11
+ @uuid_with_json = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, {"im" => "json"})
12
+ end
13
+
14
+ describe ".get" do
15
+ it "return the status as a Resque::Plugins::Status::Hash for the uuid" do
16
+ status = Resque::Plugins::Status::Hash.get(@uuid)
17
+ assert status.is_a?(Resque::Plugins::Status::Hash)
18
+ assert_equal 'my status', status.message
19
+ end
20
+
21
+ it "return nil if the status is not set" do
22
+ assert_nil Resque::Plugins::Status::Hash.get('invalid_uuid')
23
+ end
24
+
25
+ it "decode encoded json" do
26
+ assert_equal("json", Resque::Plugins::Status::Hash.get(@uuid_with_json)['im'])
27
+ end
28
+ end
29
+
30
+ describe ".mget" do
31
+ it "return statuses as array of Resque::Plugins::Status::Hash for the uuids" do
32
+ uuid2 = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
33
+ Resque::Plugins::Status::Hash.set(uuid2, "my status2")
34
+ statuses = Resque::Plugins::Status::Hash.mget([@uuid, uuid2])
35
+ assert_equal 2, statuses.size
36
+ assert statuses.all?{|s| s.is_a?(Resque::Plugins::Status::Hash) }
37
+ assert_equal ['my status', 'my status2'], statuses.map(&:message)
38
+ end
39
+
40
+ it "return nil if a status is not set" do
41
+ statuses = Resque::Plugins::Status::Hash.mget(['invalid_uuid', @uuid])
42
+ assert_equal 2, statuses.size
43
+ assert_nil statuses[0]
44
+ assert statuses[1].is_a?(Resque::Plugins::Status::Hash)
45
+ assert_equal 'my status', statuses[1].message
46
+ end
47
+
48
+ it "decode encoded json" do
49
+ assert_equal ['json'],
50
+ Resque::Plugins::Status::Hash.mget([@uuid_with_json]).map{|h| h['im']}
51
+ end
52
+ end
53
+
54
+ describe ".set" do
55
+
56
+ it "set the status for the uuid" do
57
+ assert Resque::Plugins::Status::Hash.set(@uuid, "updated")
58
+ assert_equal "updated", Resque::Plugins::Status::Hash.get(@uuid).message
59
+ end
60
+
61
+ it "return the status" do
62
+ assert Resque::Plugins::Status::Hash.set(@uuid, "updated").is_a?(Resque::Plugins::Status::Hash)
63
+ end
64
+
65
+ end
66
+
67
+ describe ".create" do
68
+ it "add an item to a key set" do
69
+ before = Resque::Plugins::Status::Hash.status_ids.length
70
+ Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
71
+ after = Resque::Plugins::Status::Hash.status_ids.length
72
+ assert_equal 1, after - before
73
+ end
74
+
75
+ it "return a uuid" do
76
+ assert_match(/^\w{32}$/, Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid))
77
+ end
78
+
79
+ it "store any status passed" do
80
+ uuid = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, "initial status")
81
+ status = Resque::Plugins::Status::Hash.get(uuid)
82
+ assert status.is_a?(Resque::Plugins::Status::Hash)
83
+ assert_equal "initial status", status.message
84
+ end
85
+
86
+ it "expire keys if expire_in is set" do
87
+ Resque::Plugins::Status::Hash.expire_in = 1
88
+ uuid = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, "new status")
89
+ assert_includes Resque::Plugins::Status::Hash.status_ids, uuid
90
+ assert_equal "new status", Resque::Plugins::Status::Hash.get(uuid).message
91
+ sleep 2
92
+ Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
93
+ refute_includes Resque::Plugins::Status::Hash.status_ids, uuid
94
+ assert_nil Resque::Plugins::Status::Hash.get(uuid)
95
+ end
96
+
97
+ it "store the options for the job created" do
98
+ uuid = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, "new", :options => {'test' => '123'})
99
+ assert uuid
100
+ status = Resque::Plugins::Status::Hash.get(uuid)
101
+ assert status.is_a?(Resque::Plugins::Status::Hash)
102
+ assert_equal '123', status.options['test']
103
+ end
104
+ end
105
+
106
+ describe ".clear" do
107
+ before do
108
+ Resque::Plugins::Status::Hash.clear
109
+ end
110
+
111
+ it "clear any statuses" do
112
+ assert_nil Resque::Plugins::Status::Hash.get(@uuid)
113
+ end
114
+
115
+ it "clear any recent statuses" do
116
+ assert Resque::Plugins::Status::Hash.status_ids.empty?
117
+ end
118
+
119
+ end
120
+
121
+ describe ".clear_completed" do
122
+ before do
123
+ @completed_status_id = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, {'status' => "completed"})
124
+ @not_completed_status_id = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
125
+ Resque::Plugins::Status::Hash.clear_completed
126
+ end
127
+
128
+ it "clear completed status" do
129
+ assert_nil Resque::Plugins::Status::Hash.get(@completed_status_id)
130
+ end
131
+
132
+ it "not clear not-completed status" do
133
+ status = Resque::Plugins::Status::Hash.get(@not_completed_status_id)
134
+ assert status.is_a?(Resque::Plugins::Status::Hash)
135
+ end
136
+ end
137
+
138
+ describe ".clear_failed" do
139
+ before do
140
+ @failed_status_id = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, {'status' => "failed"})
141
+ @not_failed_status_id = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid)
142
+ Resque::Plugins::Status::Hash.clear_failed
143
+ end
144
+
145
+ it "clear failed status" do
146
+ assert_nil Resque::Plugins::Status::Hash.get(@failed_status_id)
147
+ end
148
+
149
+ it "not clear not-failed status" do
150
+ status = Resque::Plugins::Status::Hash.get(@not_failed_status_id)
151
+ assert status.is_a?(Resque::Plugins::Status::Hash)
152
+ end
153
+ end
154
+
155
+ describe ".remove" do
156
+ before do
157
+ Resque::Plugins::Status::Hash.remove(@uuid)
158
+ end
159
+
160
+ it "clear specify status" do
161
+ assert_nil Resque::Plugins::Status::Hash.get(@uuid)
162
+ end
163
+ end
164
+
165
+ describe ".status_ids" do
166
+
167
+ before do
168
+ @uuids = []
169
+ 30.times{ Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid) }
170
+ end
171
+
172
+ it "return an array of job ids" do
173
+ assert Resque::Plugins::Status::Hash.status_ids.is_a?(Array)
174
+ assert_equal 32, Resque::Plugins::Status::Hash.status_ids.size # 30 + 2
175
+ end
176
+
177
+ it "let you paginate through the statuses" do
178
+ assert_equal Resque::Plugins::Status::Hash.status_ids[0, 10], Resque::Plugins::Status::Hash.status_ids(0, 9)
179
+ assert_equal Resque::Plugins::Status::Hash.status_ids[10, 10], Resque::Plugins::Status::Hash.status_ids(10, 19)
180
+ # assert_equal Resque::Plugins::Status::Hash.status_ids.reverse[0, 10], Resque::Plugins::Status::Hash.status_ids(0, 10)
181
+ end
182
+ end
183
+
184
+ describe ".statuses" do
185
+
186
+ it "return an array status objects" do
187
+ statuses = Resque::Plugins::Status::Hash.statuses
188
+ assert statuses.is_a?(Array)
189
+ assert_equal [@uuid_with_json, @uuid].sort, statuses.map(&:uuid).sort
190
+ end
191
+
192
+ it "return an empty array when no statuses are available" do
193
+ Resque.redis.flushall
194
+ statuses = Resque::Plugins::Status::Hash.statuses
195
+ assert_equal [], statuses
196
+ end
197
+
198
+ end
199
+
200
+ Resque::Plugins::Status::STATUSES.each do |status_code|
201
+ describe ".#{status_code}?" do
202
+
203
+ before do
204
+ uuid = Resque::Plugins::Status::Hash.create(Resque::Plugins::Status::Hash.generate_uuid, {'status' => status_code})
205
+ @status = Resque::Plugins::Status::Hash.get(uuid)
206
+ end
207
+
208
+ it "return true for the current status" do
209
+ assert @status.send("#{status_code}?"), status_code
210
+ end
211
+
212
+ it "return false for other statuses" do
213
+ (Resque::Plugins::Status::STATUSES - [status_code]).each do |other_status_code|
214
+ assert !@status.send("#{other_status_code}?"), other_status_code
215
+ end
216
+ end
217
+
218
+ end
219
+ end
220
+ end
221
+
222
+ end