rekiq 0.0.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/.gitignore +23 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +2 -0
- data/example/sidekiq.yml +6 -0
- data/example/test_app.rb +30 -0
- data/lib/rekiq/configuration.rb +33 -0
- data/lib/rekiq/exceptions.rb +4 -0
- data/lib/rekiq/job.rb +103 -0
- data/lib/rekiq/middleware/utils.rb +14 -0
- data/lib/rekiq/middleware/work_overseer.rb +58 -0
- data/lib/rekiq/schedule_format_validator.rb +16 -0
- data/lib/rekiq/scheduler.rb +42 -0
- data/lib/rekiq/version.rb +3 -0
- data/lib/rekiq/worker.rb +62 -0
- data/lib/rekiq.rb +22 -0
- data/rekiq.gemspec +31 -0
- data/spec/factories/job.rb +15 -0
- data/spec/rekiq/job_spec.rb +400 -0
- data/spec/rekiq/middleware/utils_spec.rb +48 -0
- data/spec/rekiq/middleware/work_overseer_spec.rb +66 -0
- data/spec/rekiq/scheduler_spec.rb +61 -0
- data/spec/rekiq/worker_spec.rb +73 -0
- data/spec/spec_helper.rb +35 -0
- metadata +207 -0
@@ -0,0 +1,400 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rekiq::Job do
|
4
|
+
describe '#new' do
|
5
|
+
context 'when no args' do
|
6
|
+
before { @job = Rekiq::Job.new }
|
7
|
+
|
8
|
+
it 'returns an instance of Job' do
|
9
|
+
expect(@job).not_to be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'sets attribute shift as 0' do
|
13
|
+
expect(@job.shift).to eq(0)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sets reschedule_post_work as nil' do
|
17
|
+
expect(@job.reschedule_post_work).to eq(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'sets schedule_expired as nil' do
|
21
|
+
expect(@job.schedule_expired).to eq(nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when shift passed as argument' do
|
26
|
+
let(:shift) { 5 * 60 }
|
27
|
+
before do
|
28
|
+
@job = Rekiq::Job.new('shift' => shift)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sets shift to passed value' do
|
32
|
+
expect(@job.shift).to eq(shift)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when reschedule_post_work and ' \
|
37
|
+
'schedule_expired passed as true' do
|
38
|
+
let(:reschedule_post_work) { true }
|
39
|
+
let(:schedule_expired) { true }
|
40
|
+
before do
|
41
|
+
@job =
|
42
|
+
Rekiq::Job.new \
|
43
|
+
'reschedule_post_work' => reschedule_post_work,
|
44
|
+
'schedule_expired' => schedule_expired
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sets reschedule_post_work to true' do
|
48
|
+
expect(@job.reschedule_post_work).to eq(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets schedule_expired to true' do
|
52
|
+
expect(@job.schedule_expired).to eq(true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#from_short_key_hash' do
|
58
|
+
context 'hash returned from Job#to_short_key_hash' do
|
59
|
+
let(:job) { build(:job, :randomized_attributes) }
|
60
|
+
let(:hash) { job.to_short_key_hash }
|
61
|
+
before { @job = Rekiq::Job.from_short_key_hash(hash) }
|
62
|
+
|
63
|
+
it 'returns job instance' do
|
64
|
+
expect(@job.class).to eq(Rekiq::Job)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns job with shift value before serialization' do
|
68
|
+
expect(@job.shift).to eq(job.shift)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'returns job with reschedule_post_work value before serialization' do
|
72
|
+
expect(@job.reschedule_post_work).to eq(job.reschedule_post_work)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns job with schedule_expired value before serialization' do
|
76
|
+
expect(@job.schedule_expired).to eq(job.schedule_expired)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns job with expiration_margin value before serialization' do
|
80
|
+
expect(@job.expiration_margin).to eq(job.expiration_margin)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'returns job with schedule value before serialization' do
|
84
|
+
expect(@job.schedule.class).to eq(job.schedule.class)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'returns job with working schedule' do
|
88
|
+
time = Time.now
|
89
|
+
expect(@job.schedule.next_occurrence(time)).to(
|
90
|
+
eq(job.schedule.next_occurrence(time))
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '.to_short_key_hash' do
|
97
|
+
context 'given job instance' do
|
98
|
+
let(:job) { build(:job, :randomized_attributes) }
|
99
|
+
before { @val = job.to_short_key_hash }
|
100
|
+
|
101
|
+
it 'returns an hash' do
|
102
|
+
expect(@val.class).to eq(Hash)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns hash with key sft with shift value' do
|
106
|
+
expect(@val['sft']).to eq(job.shift)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'returns hash with key rpw with reschedule_post_work value' do
|
110
|
+
expect(@val['rpw']).to eq(job.reschedule_post_work)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'returns hash with key sh with schedule_expired value' do
|
114
|
+
expect(@val['se']).to eq(job.schedule_expired)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'returns hash with key em with expiration_margin value' do
|
118
|
+
expect(@val['em']).to eq(job.expiration_margin)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'returns hash with sch key with schedule serialized with YAML::dump' do
|
122
|
+
expect(@val['sch']).to eq(YAML::dump(job.schedule))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#next_work_time' do
|
128
|
+
context 'non recurring schedule in future' do
|
129
|
+
let(:exceed_by) { 10 * 60 }
|
130
|
+
let(:schedule_time) { Time.now + exceed_by }
|
131
|
+
let(:schedule) { IceCube::Schedule.new(schedule_time) }
|
132
|
+
|
133
|
+
context 'schedule expired as true' do
|
134
|
+
let(:schedule_expired) { true }
|
135
|
+
|
136
|
+
context 'calculating from current time' do
|
137
|
+
let(:job) do
|
138
|
+
build(:job, schedule: schedule, schedule_expired: schedule_expired)
|
139
|
+
end
|
140
|
+
before { @next_work_time = job.next_work_time }
|
141
|
+
|
142
|
+
it 'return schedule time' do
|
143
|
+
expect(@next_work_time).to eq(schedule_time)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'shift to time between current and schedule time' do
|
148
|
+
let(:shift) { - exceed_by / 2 }
|
149
|
+
|
150
|
+
context 'calculating from current time' do
|
151
|
+
let(:job) do
|
152
|
+
build(:job,
|
153
|
+
schedule: schedule,
|
154
|
+
schedule_expired: schedule_expired,
|
155
|
+
shift: shift)
|
156
|
+
end
|
157
|
+
before { @next_work_time = job.next_work_time }
|
158
|
+
|
159
|
+
it 'returns shifted schedule time' do
|
160
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'shift to time after schedule time' do
|
166
|
+
let(:shift) { 60 }
|
167
|
+
|
168
|
+
context 'calculating from current time' do
|
169
|
+
let(:job) do
|
170
|
+
build(:job, schedule: schedule,
|
171
|
+
schedule_expired: schedule_expired,
|
172
|
+
shift: shift)
|
173
|
+
end
|
174
|
+
before { @next_work_time = job.next_work_time }
|
175
|
+
|
176
|
+
it 'returns shifted schedule time' do
|
177
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'shift to time before current time' do
|
183
|
+
let(:shift) { - (schedule_time - Time.now + 60) }
|
184
|
+
|
185
|
+
context 'calculating from current time' do
|
186
|
+
let(:job) do
|
187
|
+
build(:job, schedule: schedule,
|
188
|
+
schedule_expired: schedule_expired,
|
189
|
+
shift: shift)
|
190
|
+
end
|
191
|
+
before { @next_work_time = job.next_work_time }
|
192
|
+
|
193
|
+
it 'returns shifted schedule time' do
|
194
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'schedule expired as false' do
|
201
|
+
let(:schedule_expired) { false }
|
202
|
+
let(:expiration_margin) { 10 * 60 }
|
203
|
+
|
204
|
+
context 'calculating from current time' do
|
205
|
+
let(:job) do
|
206
|
+
build(:job, schedule: schedule,
|
207
|
+
schedule_expired: schedule_expired,
|
208
|
+
expiration_margin: expiration_margin)
|
209
|
+
end
|
210
|
+
before { @next_work_time = job.next_work_time }
|
211
|
+
|
212
|
+
it 'returns schedule time' do
|
213
|
+
expect(@next_work_time).to eq(schedule_time)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'shift to time between current and schedule time' do
|
218
|
+
let(:shift) { - exceed_by / 2 }
|
219
|
+
|
220
|
+
context 'calculating from current time' do
|
221
|
+
let(:job) do
|
222
|
+
build(:job, schedule: schedule,
|
223
|
+
schedule_expired: schedule_expired,
|
224
|
+
expiration_margin: expiration_margin,
|
225
|
+
shift: shift)
|
226
|
+
end
|
227
|
+
before { @next_work_time = job.next_work_time }
|
228
|
+
|
229
|
+
it 'returns shifted schedule time' do
|
230
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'shift to time after schedule time' do
|
236
|
+
let(:shift) { 60 }
|
237
|
+
|
238
|
+
context 'calculating from current time' do
|
239
|
+
let(:job) do
|
240
|
+
build(:job, schedule: schedule,
|
241
|
+
schedule_expired: schedule_expired,
|
242
|
+
expiration_margin: expiration_margin,
|
243
|
+
shift: shift)
|
244
|
+
end
|
245
|
+
before { @next_work_time = job.next_work_time }
|
246
|
+
|
247
|
+
it 'returns shifted schedule time' do
|
248
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'shift to time inside expired margin' do
|
254
|
+
let(:shift) { - (schedule_time - Time.now + expiration_margin / 2) }
|
255
|
+
|
256
|
+
context 'calculating from current time' do
|
257
|
+
let(:job) do
|
258
|
+
build(:job, schedule: schedule,
|
259
|
+
schedule_expired: schedule_expired,
|
260
|
+
expiration_margin: expiration_margin,
|
261
|
+
shift: shift)
|
262
|
+
end
|
263
|
+
before { @next_work_time = job.next_work_time }
|
264
|
+
|
265
|
+
it 'returns shifted schedule time' do
|
266
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'shift to time before expired margin' do
|
272
|
+
let(:shift) { - (schedule_time - Time.now + expiration_margin * 2) }
|
273
|
+
|
274
|
+
context 'calculating from current time' do
|
275
|
+
let(:job) do
|
276
|
+
build(:job, schedule: schedule,
|
277
|
+
schedule_expired: schedule_expired,
|
278
|
+
expiration_margin: expiration_margin,
|
279
|
+
shift: shift)
|
280
|
+
end
|
281
|
+
before { @next_work_time = job.next_work_time }
|
282
|
+
|
283
|
+
it 'returns nil' do
|
284
|
+
expect(@next_work_time).to be_nil
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'non recurring expired schedule' do
|
292
|
+
let(:expired_by) { 10 * 60 }
|
293
|
+
let(:schedule_time) { Time.now - expired_by }
|
294
|
+
let(:schedule) { IceCube::Schedule.new(schedule_time) }
|
295
|
+
|
296
|
+
context 'schedule expired as true' do
|
297
|
+
let(:schedule_expired) { true }
|
298
|
+
|
299
|
+
context 'calculating from current time' do
|
300
|
+
let(:job) do
|
301
|
+
build(:job, schedule: schedule,
|
302
|
+
schedule_expired: schedule_expired)
|
303
|
+
end
|
304
|
+
before { @next_work_time = job.next_work_time }
|
305
|
+
|
306
|
+
it 'returns nil' do
|
307
|
+
expect(@next_work_time).to be_nil
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'calculating from before schedule time' do
|
312
|
+
let(:from) { schedule_time - 60 }
|
313
|
+
let(:job) do
|
314
|
+
build(:job, schedule: schedule,
|
315
|
+
schedule_expired: schedule_expired)
|
316
|
+
end
|
317
|
+
before { @next_work_time = job.next_work_time(from) }
|
318
|
+
|
319
|
+
it 'returns schedule time' do
|
320
|
+
expect(@next_work_time).to eq(schedule_time)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'shift to after current time' do
|
325
|
+
let(:shift) { expired_by * 2 }
|
326
|
+
|
327
|
+
context 'calculating from current time' do
|
328
|
+
let(:job) do
|
329
|
+
build(:job, schedule: schedule,
|
330
|
+
schedule_expired: schedule_expired,
|
331
|
+
shift: shift)
|
332
|
+
end
|
333
|
+
before { @next_work_time = job.next_work_time }
|
334
|
+
|
335
|
+
it 'returns shifted schedule time' do
|
336
|
+
expect(@next_work_time).to eq(schedule_time + shift)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
context 'schedule expired as false' do
|
343
|
+
let(:schedule_expired) { false }
|
344
|
+
|
345
|
+
context 'expiration margin as 0' do
|
346
|
+
let(:expiration_margin) { 0 }
|
347
|
+
|
348
|
+
context 'calculating from current time' do
|
349
|
+
let(:job) do
|
350
|
+
build(:job, schedule: schedule,
|
351
|
+
schedule_expired: schedule_expired,
|
352
|
+
expiration_margin: expiration_margin)
|
353
|
+
end
|
354
|
+
before { @next_work_time = job.next_work_time }
|
355
|
+
|
356
|
+
it 'returns nil' do
|
357
|
+
expect(@next_work_time).to be_nil
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context 'expiration margin above expiration time' do
|
363
|
+
let(:expiration_margin) { expired_by * 2 }
|
364
|
+
|
365
|
+
context 'calculating from before schedule time' do
|
366
|
+
let(:from) { schedule_time - expiration_margin - 60 }
|
367
|
+
let(:job) do
|
368
|
+
build(:job, schedule: schedule,
|
369
|
+
expiration_margin: expiration_margin,
|
370
|
+
schedule_expired: schedule_expired)
|
371
|
+
end
|
372
|
+
before { @next_work_time = job.next_work_time(from) }
|
373
|
+
|
374
|
+
it 'returns schedule time' do
|
375
|
+
expect(@next_work_time).to eq(schedule_time)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
context 'expiration margin above expiration time' do
|
381
|
+
let(:expiration_margin) { expired_by / 2 }
|
382
|
+
|
383
|
+
context 'calculating from before schedule time' do
|
384
|
+
let(:from) { schedule_time - expiration_margin - 60 }
|
385
|
+
let(:job) do
|
386
|
+
build(:job, schedule: schedule,
|
387
|
+
expiration_margin: expiration_margin,
|
388
|
+
schedule_expired: schedule_expired)
|
389
|
+
end
|
390
|
+
before { @next_work_time = job.next_work_time(from) }
|
391
|
+
|
392
|
+
it 'returns nil' do
|
393
|
+
expect(@next_work_time).to be_nil
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rekiq::Middleware::Utils do
|
4
|
+
class UtilsTestWorker
|
5
|
+
include Sidekiq::Worker
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#call' do
|
9
|
+
let(:worker) { UtilsTestWorker.new }
|
10
|
+
let(:queue) { UtilsTestWorker.get_sidekiq_options['queue'] }
|
11
|
+
let(:scheduled_work_time) { Time.at(Time.now.to_f) }
|
12
|
+
|
13
|
+
context 'worker responds to scheduled_work_time' do
|
14
|
+
context 'msg hash has rq:at key with value Time' do
|
15
|
+
let(:msg) { { 'rq:at' => scheduled_work_time.to_f } }
|
16
|
+
|
17
|
+
it 'yields passed block' do
|
18
|
+
expect do |b|
|
19
|
+
Rekiq::Middleware::Utils.new
|
20
|
+
.call(worker, msg, queue, &b)
|
21
|
+
end.to yield_control.once
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets scheduled_work_time attribute in worker' do
|
25
|
+
Rekiq::Middleware::Utils.new
|
26
|
+
.call(worker, msg, queue) {}
|
27
|
+
|
28
|
+
expect(worker.scheduled_work_time).to eq(scheduled_work_time.utc)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'msg has no key' do
|
33
|
+
let(:msg) { {} }
|
34
|
+
|
35
|
+
it 'yields passed block' do
|
36
|
+
expect do |b|
|
37
|
+
Rekiq::Middleware::Utils.new
|
38
|
+
.call(worker, msg, queue, &b)
|
39
|
+
end.to yield_control.once
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'scheduled_work_time remaing unchanged' do
|
43
|
+
expect(worker.scheduled_work_time).to be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rekiq::Middleware::WorkOverseer do
|
4
|
+
class WorkOverseerTestWorker
|
5
|
+
include Sidekiq::Worker
|
6
|
+
|
7
|
+
sidekiq_options queue: 'work_overseer_test_worker'
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#call' do
|
11
|
+
let(:worker) { WorkOverseerTestWorker.new }
|
12
|
+
let(:queue) { WorkOverseerTestWorker.get_sidekiq_options['queue'] }
|
13
|
+
let(:args) { [] }
|
14
|
+
let(:schedule) { IceCube::Schedule.new(Time.new + 3600) }
|
15
|
+
|
16
|
+
context 'msg with rq:job key (existing job)' do
|
17
|
+
let(:job) { build(:job, schedule: schedule) }
|
18
|
+
let(:msg) { { 'rq:job' => job.to_short_key_hash, 'args' => args } }
|
19
|
+
|
20
|
+
it 'yields once' do
|
21
|
+
expect do |b|
|
22
|
+
Rekiq::Middleware::WorkOverseer.new
|
23
|
+
.call(worker, msg, queue, &b)
|
24
|
+
end.to yield_control.once
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'schedules job' do
|
28
|
+
Rekiq::Middleware::WorkOverseer.new
|
29
|
+
.call(worker, msg, queue) {}
|
30
|
+
|
31
|
+
expect(WorkOverseerTestWorker.jobs.count).to eq(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'msg without rq:job key' do
|
36
|
+
let(:msg) { {} }
|
37
|
+
|
38
|
+
it 'yields once' do
|
39
|
+
expect do |b|
|
40
|
+
Rekiq::Middleware::WorkOverseer.new
|
41
|
+
.call(worker, msg, queue, &b)
|
42
|
+
end.to yield_control.once
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'msg with job retry info and rq:job (existing job)' do
|
47
|
+
let(:job) { build(:job, schedule: schedule) }
|
48
|
+
let(:msg) { { 'rq:job' => job.to_short_key_hash, 'retry_count' => 0,
|
49
|
+
'args' => args } }
|
50
|
+
|
51
|
+
it 'yields once' do
|
52
|
+
expect do |b|
|
53
|
+
Rekiq::Middleware::WorkOverseer.new
|
54
|
+
.call(worker, msg, queue, &b)
|
55
|
+
end.to yield_control.once
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not schedule work' do
|
59
|
+
Rekiq::Middleware::WorkOverseer.new
|
60
|
+
.call(worker, msg, queue) {}
|
61
|
+
|
62
|
+
expect(WorkOverseerTestWorker.jobs.count).to eq(0)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rekiq::Scheduler do
|
4
|
+
describe '#schedule' do
|
5
|
+
context 'given existing worker' do
|
6
|
+
class SchedulerTestWorker
|
7
|
+
include Sidekiq::Worker
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:worker) { SchedulerTestWorker.name }
|
11
|
+
let(:queue) { 'test_queue' }
|
12
|
+
let(:args) { [] }
|
13
|
+
|
14
|
+
context 'given valid job' do
|
15
|
+
let(:job) { build(:job) }
|
16
|
+
|
17
|
+
context 'given not nil string as addon argument' do
|
18
|
+
let(:addon) { { 'random_key' => Time.now.to_f } }
|
19
|
+
|
20
|
+
context 'given initialized scheduler instance' do
|
21
|
+
let(:scheduler) do
|
22
|
+
Rekiq::Scheduler.new(worker, queue, args, job, addon)
|
23
|
+
end
|
24
|
+
before { @jid, @work_time = scheduler.schedule }
|
25
|
+
|
26
|
+
it 'creates sidekiq job' do
|
27
|
+
expect(SchedulerTestWorker.jobs.count).to eq(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'add key rq:addon in msg' do
|
31
|
+
expect(SchedulerTestWorker.jobs[0].key?('rq:addon')).to eq(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'sets addon value in key rq:addon' do
|
35
|
+
expect(SchedulerTestWorker.jobs[0]['rq:addon']).to eq(addon)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'give nil as addon argument' do
|
41
|
+
let(:addon) { nil }
|
42
|
+
|
43
|
+
context 'given initialized scheduler instance' do
|
44
|
+
let(:scheduler) do
|
45
|
+
Rekiq::Scheduler.new(worker, queue, args, job, addon)
|
46
|
+
end
|
47
|
+
before { @jid, @work_time = scheduler.schedule }
|
48
|
+
|
49
|
+
it 'creates sidekiq job' do
|
50
|
+
expect(SchedulerTestWorker.jobs.count).to eq(1)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does not set key addon in msg' do
|
54
|
+
expect(SchedulerTestWorker.jobs[0].key?('addon')).to eq(false)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'sidekiq'
|
3
|
+
require 'rekiq/worker'
|
4
|
+
|
5
|
+
describe Rekiq::Worker do
|
6
|
+
class ExampleWorker
|
7
|
+
include Sidekiq::Worker
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'Class includes Sidekiq::Worker module' do
|
11
|
+
it 'responds to perform_recurringly' do
|
12
|
+
ExampleWorker.respond_to? :perform_recurringly
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.perform_recurringly' do
|
16
|
+
context 'scheduled one hour from now' do
|
17
|
+
let(:time) { Time.now + 3600 }
|
18
|
+
let(:schedule) { IceCube::Schedule.new(time) }
|
19
|
+
before do
|
20
|
+
@jid = ExampleWorker.perform_recurringly(schedule)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns created jid' do
|
24
|
+
expect(@jid).not_to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'schedules worker' do
|
28
|
+
expect(ExampleWorker.jobs.count).to eq(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'schedules worker for one hour from now' do
|
32
|
+
expect(ExampleWorker.jobs[0]['at']).to eq(time.to_f)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'scheduled one hour from now ' \
|
37
|
+
'shift set to minus 5 minutes' do
|
38
|
+
let(:time) { Time.now + 3600 }
|
39
|
+
let(:schedule) { IceCube::Schedule.new(time) }
|
40
|
+
let(:shift) { -5 * 60 }
|
41
|
+
before do
|
42
|
+
@jid = ExampleWorker.perform_recurringly(schedule) do |options|
|
43
|
+
options.shift = shift
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'returns created job id' do
|
48
|
+
expect(@jid).not_to be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'schedules worker' do
|
52
|
+
expect(ExampleWorker.jobs.count).to eq(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'yields once' do
|
56
|
+
expect do |b|
|
57
|
+
ExampleWorker.perform_recurringly(schedule, &b)
|
58
|
+
end.to yield_control.once
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'sets shift in job' do
|
62
|
+
hash = ExampleWorker.jobs[0]['rq:job']
|
63
|
+
|
64
|
+
expect(hash['sft']).to eq(shift)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'schedules worker for one hour minus 5 minutes from now' do
|
68
|
+
expect(ExampleWorker.jobs[0]['at']).to eq(time.to_f + shift)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
if ENV['CODECLIMATE_REPO_TOKEN'].nil?
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
coverage_dir 'tmp/coverage'
|
5
|
+
end
|
6
|
+
else
|
7
|
+
require "codeclimate-test-reporter"
|
8
|
+
CodeClimate::TestReporter.start
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'factory_girl'
|
12
|
+
require 'pry'
|
13
|
+
require 'sidekiq'
|
14
|
+
require 'sidekiq/testing'
|
15
|
+
require 'rekiq'
|
16
|
+
|
17
|
+
# configure sidekiq for testing
|
18
|
+
Sidekiq::Testing.fake!
|
19
|
+
Sidekiq::Logging.logger = nil
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.include FactoryGirl::Syntax::Methods
|
23
|
+
|
24
|
+
config.before(:each) do
|
25
|
+
Sidekiq::Worker.clear_all
|
26
|
+
end
|
27
|
+
|
28
|
+
config.after(:suite) do
|
29
|
+
Sidekiq::Worker.clear_all
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# configure factory girl
|
34
|
+
FactoryGirl.definition_file_paths = %w{./spec/factories}
|
35
|
+
FactoryGirl.find_definitions
|