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.
@@ -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
@@ -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