rekiq 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,309 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rekiq::Contract do
4
+ describe '.new' do
5
+ context 'when no args' do
6
+ before { @contract = Rekiq::Contract.new }
7
+
8
+ it 'returns an instance of Contract' do
9
+ expect(@contract).not_to be_nil
10
+ end
11
+
12
+ it 'sets attribute work_time_shift as nil' do
13
+ expect(@contract.work_time_shift).to eq(nil)
14
+ end
15
+
16
+ it 'sets schedule_post_work as nil' do
17
+ expect(@contract.schedule_post_work).to eq(nil)
18
+ end
19
+
20
+ it 'sets schedule_expired as nil' do
21
+ expect(@contract.schedule_expired).to eq(nil)
22
+ end
23
+ end
24
+
25
+ context 'when work_time_shift passed as argument' do
26
+ let(:work_time_shift) { 5 * 60 }
27
+ before do
28
+ @contract = Rekiq::Contract.new('work_time_shift' => work_time_shift)
29
+ end
30
+
31
+ it 'sets work_time_shift to passed value' do
32
+ expect(@contract.work_time_shift).to eq(work_time_shift)
33
+ end
34
+ end
35
+
36
+ context 'when schedule_post_work and ' \
37
+ 'schedule_expired passed as true' do
38
+ let(:schedule_post_work) { true }
39
+ let(:schedule_expired) { true }
40
+ before do
41
+ @contract =
42
+ Rekiq::Contract.new \
43
+ 'schedule_post_work' => schedule_post_work,
44
+ 'schedule_expired' => schedule_expired
45
+ end
46
+
47
+ it 'sets schedule_post_work to true' do
48
+ expect(@contract.schedule_post_work).to eq(true)
49
+ end
50
+
51
+ it 'sets schedule_expired to true' do
52
+ expect(@contract.schedule_expired).to eq(true)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '.to_hash' do
58
+ context 'given an hash returned from Contract#to_hash' do
59
+ let(:original_contract) { build(:contract, :randomized_attributes) }
60
+ let(:hash) { original_contract.to_hash }
61
+ before { @contract = Rekiq::Contract.from_hash(hash) }
62
+
63
+ it 'returns contract instance' do
64
+ expect(@contract.class).to eq(Rekiq::Contract)
65
+ end
66
+
67
+ it 'returns contract with cancel_args value before serialization' do
68
+ expect(@contract.cancel_args).to eq(original_contract.cancel_args)
69
+ end
70
+
71
+ it 'returns contract with addon value before serialization' do
72
+ expect(@contract.addon).to eq(original_contract.addon)
73
+ end
74
+
75
+ it 'returns contract with work_time_shift value before serialization' do
76
+ expect(@contract.work_time_shift).to eq(original_contract.work_time_shift)
77
+ end
78
+
79
+ it 'returns contract with schedule_post_work value before serialization' do
80
+ expect(@contract.schedule_post_work).to eq(original_contract.schedule_post_work)
81
+ end
82
+
83
+ it 'returns contract with schedule_expired value before serialization' do
84
+ expect(@contract.schedule_expired).to eq(original_contract.schedule_expired)
85
+ end
86
+
87
+ it 'returns contract with work_time_tolerance value before serialization' do
88
+ expect(@contract.work_time_tolerance).to eq(original_contract.work_time_tolerance)
89
+ end
90
+
91
+ it 'returns contract with schedule value before serialization' do
92
+ expect(@contract.schedule.class).to eq(original_contract.schedule.class)
93
+ end
94
+
95
+ it 'returns contract with working schedule' do
96
+ time = Time.now
97
+ expect(@contract.schedule.next_occurrence(time))
98
+ .to eq(original_contract.schedule.next_occurrence(time))
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#to_hash' do
104
+ context 'given contract instance' do
105
+ let(:contract) { build(:contract, :randomized_attributes) }
106
+ before { @val = contract.to_hash }
107
+
108
+ it 'returns an hash' do
109
+ expect(@val.class).to eq(Hash)
110
+ end
111
+
112
+ it 'returns hash with Marshalled schedule under key s' do
113
+ # TODO: expect(@val[0]).to eq(Marshal.dump(contract.schedule))
114
+ end
115
+
116
+ it 'returns hash with cancel_args under key ca' do
117
+ expect(@val['ca']).to eq(contract.cancel_args)
118
+ end
119
+
120
+ it 'returns hash with addon value under key ao' do
121
+ expect(@val['ao']).to eq(contract.addon)
122
+ end
123
+
124
+ it 'returns hash with schedule_post_work value under key pw' do
125
+ expect(@val['pw']).to eq(contract.schedule_post_work)
126
+ end
127
+
128
+ it 'returns hash with work_time_shift value under key ws' do
129
+ expect(@val['ws']).to eq(contract.work_time_shift)
130
+ end
131
+
132
+ it 'returns hash with work_time_tolerance value under key wt' do
133
+ expect(@val['wt']).to eq(contract.work_time_tolerance)
134
+ end
135
+
136
+ it 'returns hash with schedule_expired value under key se' do
137
+ expect(@val['se']).to eq(contract.schedule_expired)
138
+ end
139
+ end
140
+ end
141
+
142
+ describe '#initial_work_time' do
143
+ context 'when invoked with current_time' do
144
+ let(:current_time) { Time.now }
145
+ let(:work_time_shift) { nil }
146
+ let(:work_time_tolerance) { nil }
147
+ let(:schedule_rrule) { nil }
148
+ let(:schedule) do
149
+ IceCube::Schedule.new(start_time) do |s|
150
+ s.rrule(schedule_rrule) unless schedule_rrule.nil?
151
+ end
152
+ end
153
+ let(:contract) do
154
+ build :contract,
155
+ schedule: schedule,
156
+ work_time_shift: work_time_shift,
157
+ work_time_tolerance: work_time_tolerance,
158
+ schedule_expired: schedule_expired
159
+ end
160
+ before { @work_time = contract.initial_work_time(current_time) }
161
+
162
+ context 'with non recurring schedule with start_time in future' do
163
+ let(:exceed_by) { 10 * 60 }
164
+ let(:start_time) { current_time + exceed_by }
165
+
166
+ context 'schedule_expired as true' do
167
+ let(:schedule_expired) { true }
168
+
169
+ it 'returns start_time' do
170
+ expect(@work_time).to eq(start_time)
171
+ end
172
+
173
+ context 'work_time_shift to time between current and start_time' do
174
+ let(:work_time_shift) { - exceed_by / 2 }
175
+
176
+ it 'returns shifted start_time' do
177
+ expect(@work_time).to eq(start_time + work_time_shift)
178
+ end
179
+ end
180
+
181
+ context 'work_time_shift to time after start_time' do
182
+ let(:work_time_shift) { exceed_by * 2 }
183
+
184
+ it 'returns shifted start_time' do
185
+ expect(@work_time).to eq(start_time + work_time_shift)
186
+ end
187
+ end
188
+
189
+ context 'work_time_shift to time before current_time' do
190
+ let(:work_time_shift) { - (exceed_by + 60) }
191
+
192
+ it 'returns shifted start_time' do
193
+ expect(@work_time).to eq(start_time + work_time_shift)
194
+ end
195
+ end
196
+ end
197
+
198
+ context 'schedule expired as false' do
199
+ let(:schedule_expired) { false }
200
+
201
+ it 'returns start_time' do
202
+ expect(@work_time).to eq(start_time)
203
+ end
204
+
205
+ context 'work_time_shift to time between current and start_time' do
206
+ let(:work_time_shift) { - exceed_by / 2 }
207
+
208
+ it 'returns shifted start_time' do
209
+ expect(@work_time).to eq(start_time + work_time_shift)
210
+ end
211
+ end
212
+
213
+ context 'work_time_shift to time after start_time' do
214
+ let(:work_time_shift) { 60 }
215
+
216
+ it 'returns shifted start_time' do
217
+ expect(@work_time).to eq(start_time + work_time_shift)
218
+ end
219
+ end
220
+
221
+ context 'work_time_shift to time before current' do
222
+ let(:work_time_shift) { - (exceed_by + 60) }
223
+
224
+ it 'returns nil' do
225
+ expect(@work_time).to be_nil
226
+ end
227
+ end
228
+
229
+ context 'work_time_tolerance as 10 minutes' do
230
+ let(:work_time_tolerance) { 10 * 60 }
231
+
232
+ it 'returns start_time' do
233
+ expect(@work_time).to eq(start_time)
234
+ end
235
+
236
+ context 'work_time_shift to time between current and start_time' do
237
+ let(:work_time_shift) { - exceed_by / 2 }
238
+
239
+ it 'returns shifted start_time' do
240
+ expect(@work_time).to eq(start_time + work_time_shift)
241
+ end
242
+ end
243
+
244
+ context 'work_time_shift to time after start_time' do
245
+ let(:work_time_shift) { 60 }
246
+
247
+ it 'returns shifted start_time' do
248
+ expect(@work_time).to eq(start_time + work_time_shift)
249
+ end
250
+ end
251
+
252
+ context 'work_time_shift to time inside work_time_tolerance' do
253
+ let(:work_time_shift) { - (exceed_by + work_time_tolerance / 2) }
254
+
255
+ it 'returns shifted start_time' do
256
+ expect(@work_time).to eq(start_time + work_time_shift)
257
+ end
258
+ end
259
+
260
+ context 'work_time_shift to time before work_time_tolerance' do
261
+ let(:work_time_shift) { - (exceed_by + work_time_tolerance * 2) }
262
+
263
+ it 'returns nil' do
264
+ expect(@work_time).to be_nil
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+ context 'non recurring schedule with start_time bellow current_time' do
272
+ let(:expired_by) { 10 * 60 }
273
+ let(:start_time) { current_time - expired_by }
274
+
275
+ context 'schedule expired as true' do
276
+ let(:schedule_expired) { true }
277
+
278
+ it 'returns nil' do
279
+ expect(@work_time).to be_nil
280
+ end
281
+
282
+ context 'work_time_shift to time after current_time' do
283
+ let(:work_time_shift) { expired_by * 2 }
284
+
285
+ it 'returns shifted start_time' do
286
+ expect(@work_time).to eq(start_time + work_time_shift)
287
+ end
288
+ end
289
+ end
290
+
291
+ context 'schedule_expired as false' do
292
+ let(:schedule_expired) { false }
293
+
294
+ it 'returns nil' do
295
+ expect(@work_time).to be_nil
296
+ end
297
+
298
+ context 'work_time_tolerance is above calculated expired work_time' do
299
+ let(:work_time_tolerance) { expired_by * 2 }
300
+
301
+ it 'returns start_time' do
302
+ expect(@work_time).to eq(start_time)
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
@@ -8,22 +8,21 @@ describe Rekiq::Middleware::Utils do
8
8
  describe '#call' do
9
9
  let(:worker) { UtilsTestWorker.new }
10
10
  let(:queue) { UtilsTestWorker.get_sidekiq_options['queue'] }
11
+ let(:utils) { Rekiq::Middleware::Utils.new }
11
12
  let(:scheduled_work_time) { Time.at(Time.now.to_f) }
12
13
 
13
14
  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 } }
15
+ context 'msg hash contains keys rq:ctr and rq:at' do
16
+ let(:msg) { { 'rq:ctr' => nil, 'rq:at' => scheduled_work_time.to_f } }
16
17
 
17
18
  it 'yields passed block' do
18
19
  expect do |b|
19
- Rekiq::Middleware::Utils.new
20
- .call(worker, msg, queue, &b)
20
+ utils.call(worker, msg, queue, &b)
21
21
  end.to yield_control.once
22
22
  end
23
23
 
24
24
  it 'sets scheduled_work_time attribute in worker' do
25
- Rekiq::Middleware::Utils.new
26
- .call(worker, msg, queue) {}
25
+ utils.call(worker, msg, queue) {}
27
26
 
28
27
  expect(worker.scheduled_work_time).to eq(scheduled_work_time.utc)
29
28
  end
@@ -34,12 +33,11 @@ describe Rekiq::Middleware::Utils do
34
33
 
35
34
  it 'yields passed block' do
36
35
  expect do |b|
37
- Rekiq::Middleware::Utils.new
38
- .call(worker, msg, queue, &b)
36
+ utils.call(worker, msg, queue, &b)
39
37
  end.to yield_control.once
40
38
  end
41
39
 
42
- it 'scheduled_work_time remaing unchanged' do
40
+ it 'scheduled_work_time is unchanged (nil)' do
43
41
  expect(worker.scheduled_work_time).to be_nil
44
42
  end
45
43
  end
@@ -19,19 +19,22 @@ describe Rekiq::Middleware::WorkOverseer do
19
19
  end
20
20
 
21
21
  describe '#call' do
22
- let(:args) { [] }
23
- let(:schedule) { IceCube::Schedule.new(Time.new + 3600) }
24
- let(:job) { build(:job, schedule: schedule) }
25
- let(:overseer) { Rekiq::Middleware::WorkOverseer.new }
22
+ let(:args) { [] }
23
+ let(:schedule) { IceCube::Schedule.new(Time.new + 3600) }
24
+ let(:overseer) { Rekiq::Middleware::WorkOverseer.new }
25
+ let(:cancel_args) { nil }
26
+ let(:contract) do
27
+ build :contract, schedule: schedule, cancel_args: cancel_args
28
+ end
26
29
 
27
- context 'worker does not have rekiq_cancel_method set' do
28
- let(:worker) { WorkOverseerTestWorker.new }
29
- let(:queue) { WorkOverseerTestWorker.get_sidekiq_options['queue'] }
30
+ context 'worker without rekiq_cancel_method configured' do
31
+ let(:worker) { WorkOverseerTestWorker.new }
32
+ let(:queue) { WorkOverseerTestWorker.get_sidekiq_options['queue'] }
30
33
 
31
- context 'msg with rq:job key (existing job), ' \
32
- 'with rq:schdlr key (value is irrelevant)' do
34
+ context 'msg with rq:ctr key (existing contract), ' \
35
+ 'with rq:sdl key (value is irrelevant)' do
33
36
  let(:msg) do
34
- { 'rq:job' => job.to_array, 'args' => args, 'rq:schdlr' => nil }
37
+ { 'rq:ctr' => contract.to_hash, 'args' => args, 'rq:sdl' => nil }
35
38
  end
36
39
 
37
40
  it 'yields once' do
@@ -40,20 +43,20 @@ describe Rekiq::Middleware::WorkOverseer do
40
43
  end.to yield_control.once
41
44
  end
42
45
 
43
- it 'schedules job' do
46
+ it 'schedules worker' do
44
47
  overseer.call(worker, msg, queue) {}
45
48
 
46
49
  expect(WorkOverseerTestWorker.jobs.count).to eq(1)
47
50
  end
48
51
 
49
- it 'removes key rq:schdlr from message after invocation' do
52
+ it 'removes key rq:sdl from message after invocation' do
50
53
  overseer.call(worker, msg, queue) {}
51
54
 
52
- expect(msg.key?('rq:schdlr')).to eq(false)
55
+ expect(msg.key?('rq:sdl')).to eq(false)
53
56
  end
54
57
  end
55
58
 
56
- context 'msg without rq:job key' do
59
+ context 'msg without rq:ctr key' do
57
60
  let(:msg) { {} }
58
61
 
59
62
  it 'yields once' do
@@ -61,10 +64,16 @@ describe Rekiq::Middleware::WorkOverseer do
61
64
  overseer.call(worker, msg, queue, &b)
62
65
  end.to yield_control.once
63
66
  end
67
+
68
+ it 'does not schedule worker' do
69
+ overseer.call(worker, msg, queue) {}
70
+
71
+ expect(WorkOverseerTestWorker.jobs.count).to eq(0)
72
+ end
64
73
  end
65
74
 
66
- context 'msg without rq:schdlr and rq:job (existing job)' do
67
- let(:msg) { { 'rq:job' => job.to_array, 'args' => args } }
75
+ context 'msg without key rq:sdl but with key rq:ctr' do
76
+ let(:msg) { { 'rq:ctr' => contract.to_hash, 'args' => args } }
68
77
 
69
78
  it 'yields once' do
70
79
  expect do |b|
@@ -80,51 +89,64 @@ describe Rekiq::Middleware::WorkOverseer do
80
89
  end
81
90
  end
82
91
 
83
- context 'worker has rekiq_cancel_method method set' do
92
+ context 'worker with rekiq_cancel_method configured' do
84
93
  let(:worker) { WorkOverseerCancelTestWorker.new }
85
94
  let(:queue) { WorkOverseerCancelTestWorker.get_sidekiq_options['queue'] }
86
95
 
87
- context 'msg with rq:ca key with value to cancel worker' do
96
+ context 'msg with keys rc:ctr and rc:sdl' do
88
97
  let(:msg) do
89
- { 'rq:job' => job.to_array, 'args' => args, 'rq:ca' => true }
98
+ { 'rq:ctr' => contract.to_hash, 'args' => args, 'rq:sdl' => nil }
90
99
  end
91
100
 
92
- it 'does not yield' do
93
- expect do |b|
94
- overseer.call(worker, msg, queue, &b)
95
- end.not_to yield_control
96
- end
101
+ context 'work is cancelled by cancel method' do
102
+ let(:cancel_args) { true }
97
103
 
98
- it 'does not schedule worker' do
99
- expect(WorkOverseerCancelTestWorker.jobs.count).to eq(0)
100
- end
101
- end
104
+ it 'does not yield' do
105
+ expect do |b|
106
+ overseer.call(worker, msg, queue, &b)
107
+ end.not_to yield_control
108
+ end
102
109
 
103
- context 'msg with rq:ca key with value that does not cancel worker' do
104
- let(:msg) do
105
- { 'rq:job' => job.to_array, 'args' => args, 'rq:ca' => false }
106
- end
110
+ it 'does not schedule next work' do
111
+ overseer.call(worker, msg, queue) {}
107
112
 
108
- it 'yields given block' do
109
- expect do |b|
110
- overseer.call(worker, msg, queue, &b)
111
- end.to yield_control.once
113
+ expect(WorkOverseerCancelTestWorker.jobs.count).to eq(0)
114
+ end
112
115
  end
113
116
 
114
- it 'does not schedule worker' do
115
- expect(WorkOverseerCancelTestWorker.jobs.count).to eq(0)
116
- end
117
- end
117
+ context 'work is not cancelled by cancel method' do
118
+ let(:cancel_args) { false }
118
119
 
119
- context 'msg with rq:ca key with different arity from cancel method' do
120
- let(:msg) do
121
- { 'rq:job' => job.to_array, 'args' => args, 'rq:ca' => [true, true] }
120
+ it 'yields given block' do
121
+ expect do |b|
122
+ overseer.call(worker, msg, queue, &b)
123
+ end.to yield_control.once
124
+ end
125
+
126
+ it 'it schedules work' do
127
+ overseer.call(worker, msg, queue) {}
128
+
129
+ expect(WorkOverseerCancelTestWorker.jobs.count).to eq(1)
130
+ end
131
+
132
+ it 'removes key rq:sdl from message after invocation' do
133
+ overseer.call(worker, msg, queue) {}
134
+
135
+ expect(msg.key?('rq:sdl')).to eq(false)
136
+ end
122
137
  end
123
138
 
124
- it 'raises error' do
125
- expect do |b|
126
- overseer.call(worker, msg, queue, &b)
127
- end.to raise_error
139
+ context 'contract with incorrect arity of cancel_args' do
140
+ let(:cancel_args) { [true, false] }
141
+ let(:msg) do
142
+ { 'rq:ctr' => contract.to_hash, 'args' => args }
143
+ end
144
+
145
+ it 'raises error' do
146
+ expect do |b|
147
+ overseer.call(worker, msg, queue, &b)
148
+ end.to raise_error
149
+ end
128
150
  end
129
151
  end
130
152
  end
@@ -1,75 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Rekiq::Scheduler do
4
- describe '#schedule' do
4
+ describe '#schedule_initial_work' do
5
5
  context 'given existing worker' do
6
6
  class SchedulerTestWorker
7
7
  include Sidekiq::Worker
8
8
  end
9
9
 
10
- let(:worker) { SchedulerTestWorker.name }
11
- let(:queue) { 'test_queue' }
12
- let(:args) { [] }
13
- let(:addon) { nil }
14
- let(:c_args) { nil }
10
+ let(:worker_name) { SchedulerTestWorker.name }
11
+ let(:queue) { 'test_queue' }
12
+ let(:args) { [] }
15
13
  let(:scheduler) do
16
- Rekiq::Scheduler.new(worker, queue, args, job, addon, c_args)
14
+ Rekiq::Scheduler.new(worker_name, queue, args, contract)
17
15
  end
18
- before { @jid, @work_time = scheduler.schedule }
16
+ before { @jid, @work_time = scheduler.schedule_initial_work }
19
17
 
20
- context 'given valid job' do
21
- let(:job) { build(:job) }
22
-
23
- context 'give nil as addon argument' do
24
- it 'creates sidekiq job' do
25
- expect(SchedulerTestWorker.jobs.count).to eq(1)
26
- end
27
-
28
- it 'does not set key rq:addon in msg' do
29
- expect(SchedulerTestWorker.jobs[0].key?('rq:addon')).to eq(false)
30
- end
31
- end
32
-
33
- context 'given not nil string as addon argument' do
34
- let(:addon) { { 'random_key' => Time.now.to_f } }
35
-
36
- it 'creates sidekiq job' do
37
- expect(SchedulerTestWorker.jobs.count).to eq(1)
38
- end
39
-
40
- it 'add key rq:addon in msg' do
41
- expect(SchedulerTestWorker.jobs[0].key?('rq:addon')).to eq(true)
42
- end
43
-
44
- it 'sets addon value in key rq:addon' do
45
- expect(SchedulerTestWorker.jobs[0]['rq:addon']).to eq(addon)
46
- end
47
- end
18
+ context 'given valid contract' do
19
+ let(:contract) { build :contract }
48
20
 
49
21
  context 'given nil as rekiq_cancel_args' do
50
22
  it 'creates sidekiq job' do
51
23
  expect(SchedulerTestWorker.jobs.count).to eq(1)
52
24
  end
53
-
54
- it 'does not set key rq:ca in msg' do
55
- expect(SchedulerTestWorker.jobs[0].key?('rq:ca')).to eq(false)
56
- end
57
- end
58
-
59
- context 'given non empty array as rekiq_cancel_args' do
60
- let(:c_args) { [1, 2, 3] }
61
-
62
- it 'creates sidekiq job' do
63
- expect(SchedulerTestWorker.jobs.count).to eq(1)
64
- end
65
-
66
- it 'sets key rq:ca in msg' do
67
- expect(SchedulerTestWorker.jobs[0].key?('rq:ca')).to eq(true)
68
- end
69
-
70
- it 'sets key rq:ca in msg with passed value' do
71
- expect(SchedulerTestWorker.jobs[0]['rq:ca']).to eq(c_args)
72
- end
73
25
  end
74
26
  end
75
27
  end