que 0.4.0 → 0.5.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.
@@ -7,11 +7,11 @@ describe Que::Job, '.queue' do
7
7
  DB[:que_jobs].count.should be 1
8
8
 
9
9
  result.should be_an_instance_of Que::Job
10
- result.attrs[:priority].should == '1'
10
+ result.attrs[:priority].should == '100'
11
11
  result.attrs[:args].should == []
12
12
 
13
13
  job = DB[:que_jobs].first
14
- job[:priority].should be 1
14
+ job[:priority].should be 100
15
15
  job[:run_at].should be_within(3).of Time.now
16
16
  job[:job_class].should == "Que::Job"
17
17
  JSON.load(job[:args]).should == []
@@ -23,7 +23,7 @@ describe Que::Job, '.queue' do
23
23
  DB[:que_jobs].count.should be 1
24
24
 
25
25
  job = DB[:que_jobs].first
26
- job[:priority].should be 1
26
+ job[:priority].should be 100
27
27
  job[:run_at].should be_within(3).of Time.now
28
28
  job[:job_class].should == "Que::Job"
29
29
  JSON.load(job[:args]).should == [1, 'two']
@@ -39,7 +39,7 @@ describe Que::Job, '.queue' do
39
39
  DB[:que_jobs].count.should be 1
40
40
 
41
41
  job = DB[:que_jobs].first
42
- job[:priority].should be 1
42
+ job[:priority].should be 100
43
43
  job[:run_at].should be_within(3).of Time.now
44
44
  job[:job_class].should == "Que::Job"
45
45
  JSON.load(job[:args]).should == [
@@ -60,7 +60,7 @@ describe Que::Job, '.queue' do
60
60
  DB[:que_jobs].count.should be 1
61
61
 
62
62
  job = DB[:que_jobs].first
63
- job[:priority].should be 1
63
+ job[:priority].should be 100
64
64
  job[:run_at].should be_within(3).of Time.now + 60
65
65
  job[:job_class].should == "Que::Job"
66
66
  JSON.load(job[:args]).should == [1]
@@ -125,12 +125,12 @@ describe Que::Job, '.queue' do
125
125
 
126
126
  first, second = DB[:que_jobs].order(:job_id).all
127
127
 
128
- first[:priority].should be 1
128
+ first[:priority].should be 100
129
129
  first[:run_at].should be_within(3).of Time.now + 60
130
130
  first[:job_class].should == "DefaultRunAtJob"
131
131
  JSON.load(first[:args]).should == [1]
132
132
 
133
- second[:priority].should be 1
133
+ second[:priority].should be 100
134
134
  second[:run_at].should be_within(3).of Time.now + 30
135
135
  second[:job_class].should == "DefaultRunAtJob"
136
136
  JSON.load(second[:args]).should == [1]
@@ -24,6 +24,9 @@ describe Que, '.worker_states' do
24
24
  states = Que.worker_states
25
25
  states.length.should be 1
26
26
 
27
+ $q2.push nil
28
+ t.join
29
+
27
30
  state = states.first
28
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)
29
32
 
@@ -42,11 +45,6 @@ describe Que, '.worker_states' do
42
45
  Time.parse(state[:pg_last_query_started_at]).should be_within(3).of Time.now
43
46
  state[:pg_transaction_started_at].should == nil
44
47
  state[:pg_waiting_on_lock].should == 'f'
45
- ensure
46
- if t
47
- t.kill
48
- t.join
49
- end
50
48
  end
51
49
  end if QUE_ADAPTERS[:connection_pool]
52
50
  end
@@ -4,7 +4,11 @@ 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
5
  ArgsJob.queue 1, 'two', {'three' => 3}
6
6
  DB[:que_jobs].count.should be 1
7
- Que::Job.work.should be_an_instance_of ArgsJob
7
+
8
+ result = Que::Job.work
9
+ result[:event].should == :job_worked
10
+ result[:job][:job_class].should == 'ArgsJob'
11
+
8
12
  DB[:que_jobs].count.should be 0
9
13
  $passed_args.should == [1, 'two', {'three' => 3}]
10
14
  end
@@ -13,33 +17,18 @@ describe Que::Job, '.work' do
13
17
  DB[:que_jobs].count.should be 0
14
18
  ArgsJob.queue 1, 'two', {'array' => [{'number' => 3}]}
15
19
  DB[:que_jobs].count.should be 1
16
- Que::Job.work.should be_an_instance_of ArgsJob
20
+
21
+ result = Que::Job.work
22
+ result[:event].should == :job_worked
23
+ result[:job][:job_class].should == 'ArgsJob'
24
+
17
25
  DB[:que_jobs].count.should be 0
18
26
 
19
27
  $passed_args.last[:array].first[:number].should == 3
20
28
  end
21
29
 
22
30
  it "should not fail if there are no jobs to work" do
23
- Que::Job.work.should be nil
24
- end
25
-
26
- it "should write messages to the logger" do
27
- Que::Job.queue
28
- Que::Job.work
29
-
30
- $logger.messages.length.should == 1
31
- $logger.messages[0].should =~ /\A\[Que\] Worked job in/
32
- end
33
-
34
- it "should not fail if there's no logger assigned" do
35
- begin
36
- Que.logger = nil
37
-
38
- Que::Job.queue
39
- Que::Job.work
40
- ensure
41
- Que.logger = $logger
42
- end
31
+ Que::Job.work[:event].should be :job_unavailable
43
32
  end
44
33
 
45
34
  it "should prefer a job with a higher priority" do
@@ -47,7 +36,9 @@ describe Que::Job, '.work' do
47
36
  [5, 4, 3, 2, 1, 2, 3, 4, 5].map{|p| Que::Job.queue :priority => p}
48
37
  DB[:que_jobs].order(:job_id).select_map(:priority).should == [5, 4, 3, 2, 1, 2, 3, 4, 5]
49
38
 
50
- Que::Job.work.should be_an_instance_of Que::Job
39
+ result = Que::Job.work
40
+ result[:event].should == :job_worked
41
+ result[:job][:job_class].should == 'Que::Job'
51
42
  DB[:que_jobs].select_map(:priority).should == [5, 4, 3, 2, 2, 3, 4, 5]
52
43
  end
53
44
 
@@ -58,7 +49,9 @@ describe Que::Job, '.work' do
58
49
 
59
50
  recent1, old, recent2 = DB[:que_jobs].order(:job_id).select_map(:run_at)
60
51
 
61
- Que::Job.work.should be_an_instance_of Que::Job
52
+ result = Que::Job.work
53
+ result[:event].should == :job_worked
54
+ result[:job][:job_class].should == 'Que::Job'
62
55
  DB[:que_jobs].order_by(:job_id).select_map(:run_at).should == [recent1, recent2]
63
56
  end
64
57
 
@@ -70,7 +63,9 @@ describe Que::Job, '.work' do
70
63
 
71
64
  first, second, third = DB[:que_jobs].select_order_map(:job_id)
72
65
 
73
- Que::Job.work.should be_an_instance_of Que::Job
66
+ result = Que::Job.work
67
+ result[:event].should == :job_worked
68
+ result[:job][:job_class].should == 'Que::Job'
74
69
  DB[:que_jobs].select_order_map(:job_id).should == [second, third]
75
70
  end
76
71
 
@@ -81,8 +76,10 @@ describe Que::Job, '.work' do
81
76
 
82
77
  future1, past, future2 = DB[:que_jobs].order(:job_id).select_map(:run_at)
83
78
 
84
- Que::Job.work.should be_an_instance_of Que::Job
85
- Que::Job.work.should be nil
79
+ result = Que::Job.work
80
+ result[:event].should == :job_worked
81
+ result[:job][:job_class].should == 'Que::Job'
82
+ Que::Job.work[:event].should be :job_unavailable
86
83
  DB[:que_jobs].order_by(:job_id).select_map(:run_at).should == [future1, future2]
87
84
  end
88
85
 
@@ -106,7 +103,11 @@ describe Que::Job, '.work' do
106
103
 
107
104
  begin
108
105
  DB.select{pg_advisory_lock(id)}.single_value
109
- Que::Job.work.should be_an_instance_of Que::Job
106
+
107
+ result = Que::Job.work
108
+ result[:event].should == :job_worked
109
+ result[:job][:job_class].should == 'Que::Job'
110
+
110
111
  DB[:que_jobs].order_by(:job_id).select_map(:priority).should == [1, 3]
111
112
  ensure
112
113
  DB.select{pg_advisory_unlock(id)}.single_value
@@ -134,13 +135,17 @@ describe Que::Job, '.work' do
134
135
  $job_spec_result = []
135
136
  SubClassJob.queue
136
137
  DB[:que_jobs].select_map(:priority).should == [2]
137
- Que::Job.work.should be_an_instance_of SubClassJob
138
+ result = Que::Job.work
139
+ result[:event].should == :job_worked
140
+ result[:job][:job_class].should == 'SubClassJob'
138
141
  $job_spec_result.should == [:sub]
139
142
 
140
143
  $job_spec_result = []
141
144
  SubSubClassJob.queue
142
145
  DB[:que_jobs].select_map(:priority).should == [4]
143
- Que::Job.work.should be_an_instance_of SubSubClassJob
146
+ result = Que::Job.work
147
+ result[:event].should == :job_worked
148
+ result[:job][:job_class].should == 'SubSubClassJob'
144
149
  $job_spec_result.should == [:sub, :subsub]
145
150
  end
146
151
 
@@ -152,7 +157,10 @@ describe Que::Job, '.work' do
152
157
 
153
158
  ModuleJobModule::ModuleJob.queue
154
159
  DB[:que_jobs].get(:job_class).should == "ModuleJobModule::ModuleJob"
155
- Que::Job.work.should be_an_instance_of ModuleJobModule::ModuleJob
160
+
161
+ result = Que::Job.work
162
+ result[:event].should == :job_worked
163
+ result[:job][:job_class].should == 'ModuleJobModule::ModuleJob'
156
164
  end
157
165
 
158
166
  it "should make it easy to destroy the job within the same transaction as other changes" do
@@ -171,7 +179,11 @@ describe Que::Job, '.work' do
171
179
  describe "when encountering an error" do
172
180
  it "should exponentially back off the job" do
173
181
  ErrorJob.queue
174
- Que::Job.work.should be true
182
+
183
+ result = Que::Job.work
184
+ result[:event].should == :job_errored
185
+ result[:error].should be_an_instance_of RuntimeError
186
+ result[:job][:job_class].should == 'ErrorJob'
175
187
 
176
188
  DB[:que_jobs].count.should be 1
177
189
  job = DB[:que_jobs].first
@@ -182,7 +194,10 @@ describe Que::Job, '.work' do
182
194
  DB[:que_jobs].update :error_count => 5,
183
195
  :run_at => Time.now - 60
184
196
 
185
- Que::Job.work.should be true
197
+ result = Que::Job.work
198
+ result[:event].should == :job_errored
199
+ result[:error].should be_an_instance_of RuntimeError
200
+ result[:job][:job_class].should == 'ErrorJob'
186
201
 
187
202
  DB[:que_jobs].count.should be 1
188
203
  job = DB[:que_jobs].first
@@ -197,7 +212,11 @@ describe Que::Job, '.work' do
197
212
  Que.error_handler = proc { |error| errors << error }
198
213
 
199
214
  ErrorJob.queue
200
- Que::Job.work.should be true
215
+
216
+ result = Que::Job.work
217
+ result[:event].should == :job_errored
218
+ result[:error].should be_an_instance_of RuntimeError
219
+ result[:job][:job_class].should == 'ErrorJob'
201
220
 
202
221
  errors.count.should be 1
203
222
  error = errors[0]
@@ -212,26 +231,23 @@ describe Que::Job, '.work' do
212
231
  begin
213
232
  Que.error_handler = proc { |error| raise "Another error!" }
214
233
  ErrorJob.queue
215
- Que::Job.work.should be true
234
+
235
+ result = Que::Job.work
236
+ result[:event].should == :job_errored
237
+ result[:error].should be_an_instance_of RuntimeError
216
238
  ensure
217
239
  Que.error_handler = nil
218
240
  end
219
241
  end
220
242
 
221
- it "should return false if the job throws a postgres error" do
222
- class PGErrorJob < Que::Job
223
- def run
224
- Que.execute "bad SQL syntax"
225
- end
226
- end
227
-
228
- PGErrorJob.queue
229
- Que::Job.work.should be false
230
- end
231
-
232
243
  it "should throw an error properly if there's no corresponding job class" do
233
244
  DB[:que_jobs].insert :job_class => "NonexistentClass"
234
- Que::Job.work.should be true
245
+
246
+ result = Que::Job.work
247
+ result[:event].should == :job_errored
248
+ result[:error].should be_an_instance_of NameError
249
+ result[:job][:job_class].should == 'NonexistentClass'
250
+
235
251
  DB[:que_jobs].count.should be 1
236
252
  job = DB[:que_jobs].first
237
253
  job[:error_count].should be 1
@@ -10,10 +10,15 @@ describe Que::Worker do
10
10
  @worker = Que::Worker.new
11
11
  sleep_until { @worker.sleeping? }
12
12
  DB[:que_jobs].count.should be 0
13
+
14
+ $logger.messages.map{|m| JSON.load(m)['event']}.should == %w(job_worked job_worked job_unavailable)
15
+
16
+ json = JSON.load($logger.messages[0])
17
+ json['job']['job_class'].should == 'Que::Job'
13
18
  ensure
14
19
  if @worker
15
- @worker.thread.kill
16
- @worker.thread.join
20
+ @worker.stop
21
+ @worker.wait_until_stopped
17
22
  end
18
23
  end
19
24
  end
@@ -32,8 +37,8 @@ describe Que::Worker do
32
37
  DB[:que_jobs].count.should be 0
33
38
  ensure
34
39
  if @worker
35
- @worker.thread.kill
36
- @worker.thread.join
40
+ @worker.stop
41
+ @worker.wait_until_stopped
37
42
  end
38
43
  end
39
44
  end
@@ -46,10 +51,11 @@ describe Que::Worker do
46
51
  $q1.pop
47
52
  DB[:que_jobs].count.should be 1
48
53
  @worker.wake!.should be nil
54
+ $q2.push nil
49
55
  ensure
50
56
  if @worker
51
- @worker.thread.kill
52
- @worker.thread.join
57
+ @worker.stop
58
+ @worker.wait_until_stopped
53
59
  end
54
60
  end
55
61
  end
@@ -67,10 +73,16 @@ describe Que::Worker do
67
73
  job = DB[:que_jobs].first
68
74
  job[:job_class].should == 'ErrorJob'
69
75
  job[:run_at].should be_within(3).of Time.now + 4
76
+
77
+ log = JSON.load($logger.messages[0])
78
+ log['event'].should == 'job_errored'
79
+ log['error']['class'].should == 'RuntimeError'
80
+ log['error']['message'].should == "ErrorJob!"
81
+ log['job']['job_class'].should == 'ErrorJob'
70
82
  ensure
71
83
  if @worker
72
- @worker.thread.kill
73
- @worker.thread.join
84
+ @worker.stop
85
+ @worker.wait_until_stopped
74
86
  end
75
87
  end
76
88
  end
@@ -92,11 +104,6 @@ describe Que::Worker do
92
104
  DB[:que_jobs].count.should be 1
93
105
  job = DB[:que_jobs].first
94
106
  job[:job_class].should == 'Que::Job'
95
- ensure
96
- if @worker
97
- @worker.thread.kill
98
- @worker.thread.join
99
- end
100
107
  end
101
108
  end
102
109
 
@@ -107,45 +114,6 @@ describe Que::Worker do
107
114
 
108
115
  @worker.stop
109
116
  @worker.wait_until_stopped
110
- ensure
111
- if @worker
112
- @worker.thread.kill
113
- @worker.thread.join
114
- end
115
- end
116
- end
117
-
118
- it "should receive and respect a notification to stop immediately when it is working, and kill the job" do
119
- begin
120
- # Worker#stop! can leave the database connection in an unpredictable
121
- # state, which would impact the rest of the tests, so we need a special
122
- # connection for it.
123
- pg = NEW_PG_CONNECTION.call
124
- Que.connection = pg
125
-
126
- BlockJob.queue
127
-
128
- @worker = Que::Worker.new
129
- $q1.pop
130
- @worker.stop!
131
- @worker.wait_until_stopped
132
- ensure
133
- pg.close if pg
134
- end
135
- end
136
-
137
- it "should receive and respect a notification to stop immediately when it is currently asleep" do
138
- begin
139
- @worker = Que::Worker.new
140
- sleep_until { @worker.sleeping? }
141
-
142
- @worker.stop!
143
- @worker.wait_until_stopped
144
- ensure
145
- if @worker
146
- @worker.thread.kill
147
- @worker.thread.join
148
- end
149
117
  end
150
118
  end
151
119
  end
@@ -49,15 +49,15 @@ task :safe_shutdown do
49
49
  puts "kill -#{signal} #{Process.pid}"
50
50
  end
51
51
 
52
- # Put exit behavior to test the behavior of here:
53
- at_exit do
54
- puts "Stopping Que..."
55
- Que.stop!
56
- end
57
-
58
52
  stop = false
59
53
  trap('INT'){stop = true}
60
54
 
55
+ at_exit do
56
+ $stdout.puts "Finishing Que's current jobs before exiting..."
57
+ Que.mode = :off
58
+ $stdout.puts "Que's jobs finished, exiting..."
59
+ end
60
+
61
61
  loop do
62
62
  sleep 0.01
63
63
  break if stop
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: que
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hanks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-06 00:00:00.000000000 Z
11
+ date: 2014-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -18,26 +18,12 @@ dependencies:
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
- prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
25
  version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: multi_json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.0'
34
- type: :runtime
35
26
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.0'
41
27
  description: A job queue that uses PostgreSQL's advisory locks for speed and reliability.
42
28
  email:
43
29
  - christopher.m.hanks@gmail.com
@@ -47,14 +33,17 @@ extra_rdoc_files: []
47
33
  files:
48
34
  - ".gitignore"
49
35
  - ".rspec"
36
+ - ".travis.yml"
50
37
  - CHANGELOG.md
51
38
  - Gemfile
52
39
  - LICENSE.txt
53
40
  - README.md
54
41
  - Rakefile
55
42
  - docs/advanced_setup.md
43
+ - docs/customizing_que.md
56
44
  - docs/error_handling.md
57
45
  - docs/inspecting_the_queue.md
46
+ - docs/logging.md
58
47
  - docs/managing_workers.md
59
48
  - docs/using_plain_connections.md
60
49
  - docs/using_sequel.md
@@ -68,6 +57,11 @@ files:
68
57
  - lib/que/adapters/pg.rb
69
58
  - lib/que/adapters/sequel.rb
70
59
  - lib/que/job.rb
60
+ - lib/que/migrations.rb
61
+ - lib/que/migrations/1-down.sql
62
+ - lib/que/migrations/1-up.sql
63
+ - lib/que/migrations/2-down.sql
64
+ - lib/que/migrations/2-up.sql
71
65
  - lib/que/railtie.rb
72
66
  - lib/que/rake_tasks.rb
73
67
  - lib/que/sql.rb
@@ -83,8 +77,11 @@ files:
83
77
  - spec/support/jobs.rb
84
78
  - spec/support/shared_examples/adapter.rb
85
79
  - spec/support/shared_examples/multi_threaded_adapter.rb
80
+ - spec/travis.rb
86
81
  - spec/unit/connection_spec.rb
87
82
  - spec/unit/helper_spec.rb
83
+ - spec/unit/logging_spec.rb
84
+ - spec/unit/migrations_spec.rb
88
85
  - spec/unit/pool_spec.rb
89
86
  - spec/unit/queue_spec.rb
90
87
  - spec/unit/states_spec.rb
@@ -114,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
111
  version: '0'
115
112
  requirements: []
116
113
  rubyforge_project:
117
- rubygems_version: 2.2.0.rc.1
114
+ rubygems_version: 2.1.5
118
115
  signing_key:
119
116
  specification_version: 4
120
117
  summary: A PostgreSQL-based Job Queue
@@ -128,8 +125,11 @@ test_files:
128
125
  - spec/support/jobs.rb
129
126
  - spec/support/shared_examples/adapter.rb
130
127
  - spec/support/shared_examples/multi_threaded_adapter.rb
128
+ - spec/travis.rb
131
129
  - spec/unit/connection_spec.rb
132
130
  - spec/unit/helper_spec.rb
131
+ - spec/unit/logging_spec.rb
132
+ - spec/unit/migrations_spec.rb
133
133
  - spec/unit/pool_spec.rb
134
134
  - spec/unit/queue_spec.rb
135
135
  - spec/unit/states_spec.rb