que 0.5.0 → 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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +21 -1
  5. data/Gemfile +5 -0
  6. data/README.md +7 -6
  7. data/docs/advanced_setup.md +14 -4
  8. data/docs/customizing_que.md +4 -4
  9. data/docs/error_handling.md +13 -1
  10. data/docs/managing_workers.md +2 -2
  11. data/docs/migrating.md +26 -0
  12. data/docs/multiple_queues.md +13 -0
  13. data/docs/shutting_down_safely.md +7 -0
  14. data/docs/writing_reliable_jobs.md +43 -0
  15. data/lib/generators/que/templates/add_que.rb +1 -1
  16. data/lib/que.rb +27 -41
  17. data/lib/que/adapters/base.rb +75 -4
  18. data/lib/que/job.rb +45 -28
  19. data/lib/que/migrations.rb +3 -2
  20. data/lib/que/migrations/{1-down.sql → 1/down.sql} +0 -0
  21. data/lib/que/migrations/{1-up.sql → 1/up.sql} +0 -0
  22. data/lib/que/migrations/{2-down.sql → 2/down.sql} +0 -0
  23. data/lib/que/migrations/{2-up.sql → 2/up.sql} +0 -0
  24. data/lib/que/migrations/3/down.sql +5 -0
  25. data/lib/que/migrations/3/up.sql +5 -0
  26. data/lib/que/sql.rb +24 -17
  27. data/lib/que/version.rb +1 -1
  28. data/lib/que/worker.rb +6 -5
  29. data/spec/adapters/active_record_spec.rb +6 -6
  30. data/spec/adapters/sequel_spec.rb +4 -4
  31. data/spec/gemfiles/Gemfile1 +18 -0
  32. data/spec/gemfiles/Gemfile2 +18 -0
  33. data/spec/support/helpers.rb +2 -1
  34. data/spec/support/shared_examples/adapter.rb +7 -3
  35. data/spec/support/shared_examples/multi_threaded_adapter.rb +2 -2
  36. data/spec/travis.rb +12 -4
  37. data/spec/unit/customization_spec.rb +148 -0
  38. data/spec/unit/{queue_spec.rb → enqueue_spec.rb} +115 -14
  39. data/spec/unit/logging_spec.rb +3 -2
  40. data/spec/unit/migrations_spec.rb +3 -2
  41. data/spec/unit/pool_spec.rb +30 -6
  42. data/spec/unit/run_spec.rb +12 -0
  43. data/spec/unit/states_spec.rb +29 -31
  44. data/spec/unit/stats_spec.rb +16 -14
  45. data/spec/unit/work_spec.rb +120 -25
  46. data/spec/unit/worker_spec.rb +55 -9
  47. data/tasks/safe_shutdown.rb +1 -1
  48. metadata +30 -17
@@ -1,12 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Logging" do
4
- it "by default should record the library and thread id in JSON" do
4
+ it "by default should record the library and hostname and thread id in JSON" do
5
5
  Que.log :event => "blah", :source => 4
6
6
  $logger.messages.count.should be 1
7
7
 
8
8
  message = JSON.load($logger.messages.first)
9
9
  message['lib'].should == 'que'
10
+ message['hostname'].should == Socket.gethostname
10
11
  message['event'].should == 'blah'
11
12
  message['source'].should == 4
12
13
  message['thread'].should == Thread.current.object_id
@@ -16,7 +17,7 @@ describe "Logging" do
16
17
  begin
17
18
  Que.logger = nil
18
19
 
19
- Que::Job.queue
20
+ Que::Job.enqueue
20
21
  worker = Que::Worker.new
21
22
  sleep_until { worker.sleeping? }
22
23
 
@@ -7,7 +7,7 @@ describe Que::Migrations do
7
7
 
8
8
  default = proc do
9
9
  result = Que.execute <<-SQL
10
- select adsrc
10
+ select adsrc::integer
11
11
  from pg_attribute a
12
12
  join pg_class c on c.oid = a.attrelid
13
13
  join pg_attrdef on adrelid = attrelid AND adnum = attnum
@@ -15,7 +15,7 @@ describe Que::Migrations do
15
15
  and attname = 'priority'
16
16
  SQL
17
17
 
18
- result.first['adsrc'].to_i
18
+ result.first[:adsrc]
19
19
  end
20
20
 
21
21
  default.call.should == 100
@@ -40,6 +40,7 @@ describe Que::Migrations do
40
40
  Que::Migrations.db_version.should == Que::Migrations::CURRENT_VERSION
41
41
  Que::Migrations.migrate! :version => 0
42
42
  Que::Migrations.db_version.should == 0
43
+ Que.db_version.should == 0
43
44
  Que::Migrations.migrate!
44
45
  Que::Migrations.db_version.should == Que::Migrations::CURRENT_VERSION
45
46
 
@@ -19,15 +19,15 @@ describe "Managing the Worker pool" do
19
19
  it "should make jobs run in the same thread as they are queued" do
20
20
  Que.mode = :sync
21
21
 
22
- ArgsJob.queue(5, :testing => "synchronous").should be_an_instance_of ArgsJob
23
- $passed_args.should == [5, {'testing' => "synchronous"}]
22
+ ArgsJob.enqueue(5, :testing => "synchronous").should be_an_instance_of ArgsJob
23
+ $passed_args.should == [5, {:testing => "synchronous"}]
24
24
  DB[:que_jobs].count.should be 0
25
25
  end
26
26
 
27
27
  it "should not affect jobs that are queued with specific run_ats" do
28
28
  Que.mode = :sync
29
29
 
30
- ArgsJob.queue(5, :testing => "synchronous", :run_at => Time.now + 60)
30
+ ArgsJob.enqueue(5, :testing => "synchronous", :run_at => Time.now + 60)
31
31
  DB[:que_jobs].select_map(:job_class).should == ["ArgsJob"]
32
32
  end
33
33
  end
@@ -132,7 +132,7 @@ describe "Managing the Worker pool" do
132
132
  Que.mode = :async
133
133
  sleep_until { Que::Worker.workers.all? &:sleeping? }
134
134
 
135
- BlockJob.queue
135
+ BlockJob.enqueue
136
136
  Que.wake!
137
137
 
138
138
  $q1.pop
@@ -158,7 +158,7 @@ describe "Managing the Worker pool" do
158
158
  Que.mode = :async
159
159
  sleep_until { Que::Worker.workers.all? &:sleeping? }
160
160
 
161
- 4.times { BlockJob.queue }
161
+ 4.times { BlockJob.enqueue }
162
162
  Que.wake_all!
163
163
  4.times { $q1.pop }
164
164
 
@@ -179,8 +179,32 @@ describe "Managing the Worker pool" do
179
179
  Que.mode = :async
180
180
  sleep_until { Que::Worker.workers.all? &:sleeping? }
181
181
  Que.wake_interval = 0.01 # 10 ms
182
- Que::Job.queue
182
+ Que::Job.enqueue
183
183
  sleep_until { DB[:que_jobs].count == 0 }
184
184
  end
185
+
186
+ it "should work jobs in the queue defined by QUE_QUEUE" do
187
+ begin
188
+ Que::Job.enqueue 1
189
+ Que::Job.enqueue 2, :queue => 'my_queue'
190
+
191
+ ENV['QUE_QUEUE'] = 'my_queue'
192
+
193
+ Que.mode = :async
194
+ sleep_until { Que::Worker.workers.all? &:sleeping? }
195
+ DB[:que_jobs].count.should be 1
196
+
197
+ job = DB[:que_jobs].first
198
+ job[:queue].should == ''
199
+ job[:args].should == '[1]'
200
+ ensure
201
+ ENV.delete('QUE_QUEUE')
202
+
203
+ if @worker
204
+ @worker.stop
205
+ @worker.wait_until_stopped
206
+ end
207
+ end
208
+ end
185
209
  end
186
210
  end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Que::Job, '.run' do
4
+ it "should immediately process the job with the arguments given to it" do
5
+ result = ArgsJob.run 1, 'two', {:three => 3}
6
+ result.should be_an_instance_of ArgsJob
7
+ result.attrs[:args].should == [1, 'two', {:three => 3}]
8
+
9
+ DB[:que_jobs].count.should be 0
10
+ $passed_args.should == [1, 'two', {:three => 3}]
11
+ end
12
+ end
@@ -6,45 +6,43 @@ describe Que, '.worker_states' do
6
6
 
7
7
  class WorkerStateJob < BlockJob
8
8
  def run
9
- $pid = Que.execute("select pg_backend_pid()").first['pg_backend_pid']
9
+ $pid = Que.execute("select pg_backend_pid()").first[:pg_backend_pid]
10
10
  super
11
11
  end
12
12
  end
13
13
 
14
- WorkerStateJob.queue :priority => 2
14
+ WorkerStateJob.enqueue :priority => 2
15
15
 
16
16
  # Ensure that the portion of the SQL query that accounts for bigint
17
17
  # job_ids functions correctly.
18
18
  DB[:que_jobs].update(:job_id => 2**33)
19
19
 
20
- begin
21
- t = Thread.new { Que::Job.work }
22
- $q1.pop
23
-
24
- states = Que.worker_states
25
- states.length.should be 1
26
-
27
- $q2.push nil
28
- t.join
29
-
30
- state = states.first
31
- state.keys.should == %w(priority run_at job_id job_class args error_count last_error pg_backend_pid pg_state pg_state_changed_at pg_last_query pg_last_query_started_at pg_transaction_started_at pg_waiting_on_lock)
32
-
33
- state[:priority].should == '2'
34
- Time.parse(state[:run_at]).should be_within(3).of Time.now
35
- state[:job_id].should == (2**33).to_s
36
- state[:job_class].should == 'WorkerStateJob'
37
- state[:args].should == '[]'
38
- state[:error_count].should == '0'
39
- state[:last_error].should be nil
40
-
41
- state[:pg_backend_pid].should == $pid.to_s
42
- state[:pg_state].should == 'idle'
43
- Time.parse(state[:pg_state_changed_at]).should be_within(3).of Time.now
44
- state[:pg_last_query].should == 'select pg_backend_pid()'
45
- Time.parse(state[:pg_last_query_started_at]).should be_within(3).of Time.now
46
- state[:pg_transaction_started_at].should == nil
47
- state[:pg_waiting_on_lock].should == 'f'
48
- end
20
+ t = Thread.new { Que::Job.work }
21
+ $q1.pop
22
+
23
+ states = Que.worker_states
24
+ states.length.should be 1
25
+
26
+ $q2.push nil
27
+ t.join
28
+
29
+ state = states.first
30
+ state.keys.should == %w(priority run_at job_id job_class args error_count last_error queue pg_backend_pid pg_state pg_state_changed_at pg_last_query pg_last_query_started_at pg_transaction_started_at pg_waiting_on_lock)
31
+
32
+ state[:priority].should == 2
33
+ state[:run_at].should be_within(3).of Time.now
34
+ state[:job_id].should == 2**33
35
+ state[:job_class].should == 'WorkerStateJob'
36
+ state[:args].should == []
37
+ state[:error_count].should == 0
38
+ state[:last_error].should be nil
39
+
40
+ state[:pg_backend_pid].should == $pid
41
+ state[:pg_state].should == 'idle'
42
+ state[:pg_state_changed_at].should be_within(3).of Time.now
43
+ state[:pg_last_query].should == 'select pg_backend_pid()'
44
+ state[:pg_last_query_started_at].should be_within(3).of Time.now
45
+ state[:pg_transaction_started_at].should == nil
46
+ state[:pg_waiting_on_lock].should == false
49
47
  end if QUE_ADAPTERS[:connection_pool]
50
48
  end
@@ -2,15 +2,15 @@ require 'spec_helper'
2
2
 
3
3
  describe Que, '.job_stats' do
4
4
  it "should return a list of the job types in the queue, their counts and the number of each currently running" do
5
- BlockJob.queue
6
- Que::Job.queue
5
+ BlockJob.enqueue
6
+ Que::Job.enqueue
7
7
 
8
8
  # Have to tweak the job_id to ensure that the portion of the SQL query
9
9
  # that accounts for bigint job_ids functions correctly.
10
10
  old = Time.now - 3600
11
11
  DB[:que_jobs].where(:job_class => "Que::Job").update(:job_id => 2**33, :error_count => 5, :run_at => old)
12
12
 
13
- Que::Job.queue
13
+ Que::Job.enqueue
14
14
 
15
15
  begin
16
16
  DB.get{pg_advisory_lock(2**33)}
@@ -20,21 +20,23 @@ describe Que, '.job_stats' do
20
20
 
21
21
  qj, bj = stats
22
22
 
23
- qj.keys.should == %w(job_class count count_working count_errored highest_error_count oldest_run_at)
23
+ qj.keys.should == %w(queue job_class count count_working count_errored highest_error_count oldest_run_at)
24
24
 
25
+ qj[:queue].should == ''
25
26
  qj[:job_class].should == 'Que::Job'
26
- qj[:count].should == '2'
27
- qj[:count_working].should == '1'
28
- qj[:count_errored].should == '1'
29
- qj[:highest_error_count].should == '5'
30
- Time.parse(qj[:oldest_run_at]).should be_within(3).of old
27
+ qj[:count].should == 2
28
+ qj[:count_working].should == 1
29
+ qj[:count_errored].should == 1
30
+ qj[:highest_error_count].should == 5
31
+ qj[:oldest_run_at].should be_within(3).of old
31
32
 
33
+ bj[:queue].should == ''
32
34
  bj[:job_class].should == 'BlockJob'
33
- bj[:count].should == '1'
34
- bj[:count_working].should == '0'
35
- bj[:count_errored].should == '0'
36
- bj[:highest_error_count].should == '0'
37
- Time.parse(bj[:oldest_run_at]).should be_within(3).of Time.now
35
+ bj[:count].should == 1
36
+ bj[:count_working].should == 0
37
+ bj[:count_errored].should == 0
38
+ bj[:highest_error_count].should == 0
39
+ bj[:oldest_run_at].should be_within(3).of Time.now
38
40
  ensure
39
41
  DB.get{pg_advisory_unlock_all{}}
40
42
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Que::Job, '.work' do
4
4
  it "should pass a job's arguments to the run method and delete it from the database" do
5
- ArgsJob.queue 1, 'two', {'three' => 3}
5
+ ArgsJob.enqueue 1, 'two', {'three' => 3}
6
6
  DB[:que_jobs].count.should be 1
7
7
 
8
8
  result = Que::Job.work
@@ -13,9 +13,38 @@ describe Que::Job, '.work' do
13
13
  $passed_args.should == [1, 'two', {'three' => 3}]
14
14
  end
15
15
 
16
+ it "should default to only working jobs without a named queue" do
17
+ Que::Job.enqueue 1, :queue => 'other_queue'
18
+ Que::Job.enqueue 2
19
+
20
+ result = Que::Job.work
21
+ result[:event].should == :job_worked
22
+ result[:job][:args].should == [2]
23
+
24
+ result = Que::Job.work
25
+ result[:event].should == :job_unavailable
26
+ end
27
+
28
+ it "should accept the name of a single queue to pull jobs from" do
29
+ Que::Job.enqueue 1, :queue => 'other_queue'
30
+ Que::Job.enqueue 2, :queue => 'other_queue'
31
+ Que::Job.enqueue 3
32
+
33
+ result = Que::Job.work(:other_queue)
34
+ result[:event].should == :job_worked
35
+ result[:job][:args].should == [1]
36
+
37
+ result = Que::Job.work('other_queue')
38
+ result[:event].should == :job_worked
39
+ result[:job][:args].should == [2]
40
+
41
+ result = Que::Job.work(:other_queue)
42
+ result[:event].should == :job_unavailable
43
+ end
44
+
16
45
  it "should make a job's argument hashes indifferently accessible" do
17
46
  DB[:que_jobs].count.should be 0
18
- ArgsJob.queue 1, 'two', {'array' => [{'number' => 3}]}
47
+ ArgsJob.enqueue 1, 'two', {'array' => [{'number' => 3}]}
19
48
  DB[:que_jobs].count.should be 1
20
49
 
21
50
  result = Que::Job.work
@@ -33,7 +62,7 @@ describe Que::Job, '.work' do
33
62
 
34
63
  it "should prefer a job with a higher priority" do
35
64
  # 1 is highest priority.
36
- [5, 4, 3, 2, 1, 2, 3, 4, 5].map{|p| Que::Job.queue :priority => p}
65
+ [5, 4, 3, 2, 1, 2, 3, 4, 5].map{|p| Que::Job.enqueue :priority => p}
37
66
  DB[:que_jobs].order(:job_id).select_map(:priority).should == [5, 4, 3, 2, 1, 2, 3, 4, 5]
38
67
 
39
68
  result = Que::Job.work
@@ -43,9 +72,9 @@ describe Que::Job, '.work' do
43
72
  end
44
73
 
45
74
  it "should prefer a job that was scheduled to run longer ago when priorities are equal" do
46
- Que::Job.queue :run_at => Time.now - 30
47
- Que::Job.queue :run_at => Time.now - 60
48
- Que::Job.queue :run_at => Time.now - 30
75
+ Que::Job.enqueue :run_at => Time.now - 30
76
+ Que::Job.enqueue :run_at => Time.now - 60
77
+ Que::Job.enqueue :run_at => Time.now - 30
49
78
 
50
79
  recent1, old, recent2 = DB[:que_jobs].order(:job_id).select_map(:run_at)
51
80
 
@@ -57,9 +86,9 @@ describe Que::Job, '.work' do
57
86
 
58
87
  it "should prefer a job that was queued earlier when priorities and run_ats are equal" do
59
88
  run_at = Time.now - 30
60
- Que::Job.queue :run_at => run_at
61
- Que::Job.queue :run_at => run_at
62
- Que::Job.queue :run_at => run_at
89
+ Que::Job.enqueue :run_at => run_at
90
+ Que::Job.enqueue :run_at => run_at
91
+ Que::Job.enqueue :run_at => run_at
63
92
 
64
93
  first, second, third = DB[:que_jobs].select_order_map(:job_id)
65
94
 
@@ -70,9 +99,9 @@ describe Que::Job, '.work' do
70
99
  end
71
100
 
72
101
  it "should only work a job whose scheduled time to run has passed" do
73
- Que::Job.queue :run_at => Time.now + 30
74
- Que::Job.queue :run_at => Time.now - 30
75
- Que::Job.queue :run_at => Time.now + 30
102
+ Que::Job.enqueue :run_at => Time.now + 30
103
+ Que::Job.enqueue :run_at => Time.now - 30
104
+ Que::Job.enqueue :run_at => Time.now + 30
76
105
 
77
106
  future1, past, future2 = DB[:que_jobs].order(:job_id).select_map(:run_at)
78
107
 
@@ -84,7 +113,7 @@ describe Que::Job, '.work' do
84
113
  end
85
114
 
86
115
  it "should lock the job it selects" do
87
- BlockJob.queue
116
+ BlockJob.enqueue
88
117
  id = DB[:que_jobs].get(:job_id)
89
118
  thread = Thread.new { Que::Job.work }
90
119
 
@@ -96,9 +125,9 @@ describe Que::Job, '.work' do
96
125
  end
97
126
 
98
127
  it "should skip jobs that are advisory-locked" do
99
- Que::Job.queue :priority => 2
100
- Que::Job.queue :priority => 1
101
- Que::Job.queue :priority => 3
128
+ Que::Job.enqueue :priority => 2
129
+ Que::Job.enqueue :priority => 1
130
+ Que::Job.enqueue :priority => 3
102
131
  id = DB[:que_jobs].where(:priority => 1).get(:job_id)
103
132
 
104
133
  begin
@@ -116,7 +145,7 @@ describe Que::Job, '.work' do
116
145
 
117
146
  it "should handle subclasses of other jobs" do
118
147
  class SubClassJob < Que::Job
119
- @default_priority = 2
148
+ @priority = 2
120
149
 
121
150
  def run
122
151
  $job_spec_result << :sub
@@ -124,7 +153,7 @@ describe Que::Job, '.work' do
124
153
  end
125
154
 
126
155
  class SubSubClassJob < SubClassJob
127
- @default_priority = 4
156
+ @priority = 4
128
157
 
129
158
  def run
130
159
  super
@@ -133,7 +162,7 @@ describe Que::Job, '.work' do
133
162
  end
134
163
 
135
164
  $job_spec_result = []
136
- SubClassJob.queue
165
+ SubClassJob.enqueue
137
166
  DB[:que_jobs].select_map(:priority).should == [2]
138
167
  result = Que::Job.work
139
168
  result[:event].should == :job_worked
@@ -141,7 +170,7 @@ describe Que::Job, '.work' do
141
170
  $job_spec_result.should == [:sub]
142
171
 
143
172
  $job_spec_result = []
144
- SubSubClassJob.queue
173
+ SubSubClassJob.enqueue
145
174
  DB[:que_jobs].select_map(:priority).should == [4]
146
175
  result = Que::Job.work
147
176
  result[:event].should == :job_worked
@@ -155,7 +184,7 @@ describe Que::Job, '.work' do
155
184
  end
156
185
  end
157
186
 
158
- ModuleJobModule::ModuleJob.queue
187
+ ModuleJobModule::ModuleJob.enqueue
159
188
  DB[:que_jobs].get(:job_class).should == "ModuleJobModule::ModuleJob"
160
189
 
161
190
  result = Que::Job.work
@@ -170,7 +199,7 @@ describe Que::Job, '.work' do
170
199
  end
171
200
  end
172
201
 
173
- DestroyJob.queue
202
+ DestroyJob.enqueue
174
203
  DB[:que_jobs].count.should be 1
175
204
  Que::Job.work
176
205
  DB[:que_jobs].count.should be 0
@@ -178,7 +207,7 @@ describe Que::Job, '.work' do
178
207
 
179
208
  describe "when encountering an error" do
180
209
  it "should exponentially back off the job" do
181
- ErrorJob.queue
210
+ ErrorJob.enqueue
182
211
 
183
212
  result = Que::Job.work
184
213
  result[:event].should == :job_errored
@@ -206,12 +235,78 @@ describe Que::Job, '.work' do
206
235
  job[:run_at].should be_within(3).of Time.now + 1299
207
236
  end
208
237
 
238
+ it "should respect a custom retry interval" do
239
+ class RetryIntervalJob < ErrorJob
240
+ @retry_interval = 5
241
+ end
242
+
243
+ RetryIntervalJob.enqueue
244
+
245
+ result = Que::Job.work
246
+ result[:event].should == :job_errored
247
+ result[:error].should be_an_instance_of RuntimeError
248
+ result[:job][:job_class].should == 'RetryIntervalJob'
249
+
250
+ DB[:que_jobs].count.should be 1
251
+ job = DB[:que_jobs].first
252
+ job[:error_count].should be 1
253
+ job[:last_error].should =~ /\AErrorJob!\n/
254
+ job[:run_at].should be_within(3).of Time.now + 5
255
+
256
+ DB[:que_jobs].update :error_count => 5,
257
+ :run_at => Time.now - 60
258
+
259
+ result = Que::Job.work
260
+ result[:event].should == :job_errored
261
+ result[:error].should be_an_instance_of RuntimeError
262
+ result[:job][:job_class].should == 'RetryIntervalJob'
263
+
264
+ DB[:que_jobs].count.should be 1
265
+ job = DB[:que_jobs].first
266
+ job[:error_count].should be 6
267
+ job[:last_error].should =~ /\AErrorJob!\n/
268
+ job[:run_at].should be_within(3).of Time.now + 5
269
+ end
270
+
271
+ it "should respect a custom retry interval formula" do
272
+ class RetryIntervalFormulaJob < ErrorJob
273
+ @retry_interval = proc { |count| count * 10 }
274
+ end
275
+
276
+ RetryIntervalFormulaJob.enqueue
277
+
278
+ result = Que::Job.work
279
+ result[:event].should == :job_errored
280
+ result[:error].should be_an_instance_of RuntimeError
281
+ result[:job][:job_class].should == 'RetryIntervalFormulaJob'
282
+
283
+ DB[:que_jobs].count.should be 1
284
+ job = DB[:que_jobs].first
285
+ job[:error_count].should be 1
286
+ job[:last_error].should =~ /\AErrorJob!\n/
287
+ job[:run_at].should be_within(3).of Time.now + 10
288
+
289
+ DB[:que_jobs].update :error_count => 5,
290
+ :run_at => Time.now - 60
291
+
292
+ result = Que::Job.work
293
+ result[:event].should == :job_errored
294
+ result[:error].should be_an_instance_of RuntimeError
295
+ result[:job][:job_class].should == 'RetryIntervalFormulaJob'
296
+
297
+ DB[:que_jobs].count.should be 1
298
+ job = DB[:que_jobs].first
299
+ job[:error_count].should be 6
300
+ job[:last_error].should =~ /\AErrorJob!\n/
301
+ job[:run_at].should be_within(3).of Time.now + 60
302
+ end
303
+
209
304
  it "should pass it to an error handler, if one is defined" do
210
305
  begin
211
306
  errors = []
212
307
  Que.error_handler = proc { |error| errors << error }
213
308
 
214
- ErrorJob.queue
309
+ ErrorJob.enqueue
215
310
 
216
311
  result = Que::Job.work
217
312
  result[:event].should == :job_errored
@@ -230,7 +325,7 @@ describe Que::Job, '.work' do
230
325
  it "should not do anything if the error handler itelf throws an error" do
231
326
  begin
232
327
  Que.error_handler = proc { |error| raise "Another error!" }
233
- ErrorJob.queue
328
+ ErrorJob.enqueue
234
329
 
235
330
  result = Que::Job.work
236
331
  result[:event].should == :job_errored